{
- if (error) {
- return {error.message}
;
- } else if (props) {
- console.log(JSON.stringify(props));
- var notifications = props.team_notifications;
- var colors = ["#A8C5D6", "#CCBEDF"];
- var count = 0;
- var notificationCards = notifications.map((notif) => {
- return (
-
- );
- });
- let notificationMesssage = notificationCards.length > 0 ? notificationCards :
- "No notifications right now!"
- return (
-
-
-
- Notifications
-
- {notificationMesssage}
-
-
-
-
- );
- }
- }}
- />
- );
- }
+ render() {
+ return (
+ {
+ if (error) {
+ return {error.message}
;
+ } else if (props) {
+ console.log(JSON.stringify(props));
+ var notifications = props.team_notifications;
+ var colors = ["#A8C5D6", "#CCBEDF"];
+ var count = 0;
+ var notificationCards = notifications.map((notif) => {
+ return (
+
+ );
+ });
+ let notificationMesssage =
+ notificationCards.length > 0
+ ? notificationCards
+ : "No notifications right now!";
+ return (
+
+
+
+
+ Notifications
+
+
+ {notificationMesssage}
+
+
+
+
+ );
+ }
+ }}
+ />
+ );
+ }
}
export default TeamNotifications;
diff --git a/client/src/components/TeamPage.js b/client/src/components/TeamPage.js
index b90f12c0..76395fae 100644
--- a/client/src/components/TeamPage.js
+++ b/client/src/components/TeamPage.js
@@ -21,6 +21,7 @@ const getTeamQuery = graphql `
picture
members {
name
+ email
school
grad_year
contact
diff --git a/client/src/components/TeamRequestsSent.js b/client/src/components/TeamRequestsSent.js
index 20ad3b57..19047c9a 100644
--- a/client/src/components/TeamRequestsSent.js
+++ b/client/src/components/TeamRequestsSent.js
@@ -1,94 +1,104 @@
-import React, { Component } from 'react';
-import { Card, Container } from 'semantic-ui-react'
-import NotificationCard from './NotificationCard';
+import React, { Component } from "react";
+import { Card, Container } from "semantic-ui-react";
+import NotificationCard from "./NotificationCard";
import { QueryRenderer } from "react-relay";
import { graphql } from "babel-plugin-relay/macro";
import environment from "./Environment";
import "./css/NotificationCard.css";
const getSentRequestsQuery = graphql`
- query TeamRequestsSentQuery {
- sent_team_notifications {
- id
- message
- bio
- idea
- sender {
- __typename
- ... on User {
- id
- name
- }
- __typename
- ... on Team {
- name
- }
+ query TeamRequestsSentQuery($sent: Boolean) {
+ team_notifications(sent: $sent) {
+ id
+ message
+ bio
+ idea
+ sender {
+ __typename
+ ... on User {
+ id
+ name
}
- senderType
- receiver {
- __typename
- ... on User {
- id
- name
- }
- __typename
- ... on Team {
- name
- }
+ __typename
+ ... on Team {
+ name
}
- resolved
+ }
+ senderType
+ receiver {
+ __typename
+ ... on User {
+ id
+ name
}
+ __typename
+ ... on Team {
+ name
+ }
+ }
+ resolved
}
+ }
`;
class TeamRequestsSent extends Component {
- render() {
- return(
- {
- if (error) {
- return {error.message}
;
- } else if (props) {
- console.log(JSON.stringify(props));
- var sent_requests = props.sent_team_notifications;
- var colors = ["#A8C5D6", "#CCBEDF"];
- var count = 0;
- var sentRequestCards = sent_requests.map((notif) => {
- return (
-
- );
- });
- return (
-
-
-
- Requests Sent
-
- {sentRequestCards}
-
-
-
-
- );
- }
- }}
- />
- );
- }
+ render() {
+ return (
+ {
+ if (error) {
+ return {error.message}
;
+ } else if (props) {
+ console.log(JSON.stringify(props));
+ var sent_requests = props.team_notifications;
+ var colors = ["#A8C5D6", "#CCBEDF"];
+ var count = 0;
+ var sentRequestCards = sent_requests.map((notif) => {
+ return (
+
+ );
+ });
+ return (
+
+
+
+
+ Requests Sent
+
+
+ {sentRequestCards}
+
+
+
+
+ );
+ }
+ }}
+ />
+ );
+ }
}
-export default TeamRequestsSent;
\ No newline at end of file
+export default TeamRequestsSent;
diff --git a/client/src/components/__generated__/MembersQuery.graphql.js b/client/src/components/__generated__/MembersQuery.graphql.js
deleted file mode 100644
index 04f691e0..00000000
--- a/client/src/components/__generated__/MembersQuery.graphql.js
+++ /dev/null
@@ -1,214 +0,0 @@
-/**
- * @flow
- * @relayHash 6d447e2993b792053877d4e8d9a51fb9
- */
-
-/* eslint-disable */
-
-'use strict';
-
-/*::
-import type { ConcreteRequest } from 'relay-runtime';
-export type MembersQueryVariables = {||};
-export type MembersQueryResponse = {|
- +user_profile: {|
- +team: ?{|
- +members: ?$ReadOnlyArray{|
- +name: ?string,
- +school: ?string,
- +grad_year: ?string,
- +contact: ?string,
- +skills: ?$ReadOnlyArray,
- +experience: ?string,
- |}>
- |}
- |}
-|};
-export type MembersQuery = {|
- variables: MembersQueryVariables,
- response: MembersQueryResponse,
-|};
-*/
-
-
-/*
-query MembersQuery {
- user_profile {
- team {
- members {
- name
- school
- grad_year
- contact
- skills
- experience
- id
- }
- id
- }
- id
- }
-}
-*/
-
-const node/*: ConcreteRequest*/ = (function(){
-var v0 = {
- "kind": "ScalarField",
- "alias": null,
- "name": "name",
- "args": null,
- "storageKey": null
-},
-v1 = {
- "kind": "ScalarField",
- "alias": null,
- "name": "school",
- "args": null,
- "storageKey": null
-},
-v2 = {
- "kind": "ScalarField",
- "alias": null,
- "name": "grad_year",
- "args": null,
- "storageKey": null
-},
-v3 = {
- "kind": "ScalarField",
- "alias": null,
- "name": "contact",
- "args": null,
- "storageKey": null
-},
-v4 = {
- "kind": "ScalarField",
- "alias": null,
- "name": "skills",
- "args": null,
- "storageKey": null
-},
-v5 = {
- "kind": "ScalarField",
- "alias": null,
- "name": "experience",
- "args": null,
- "storageKey": null
-},
-v6 = {
- "kind": "ScalarField",
- "alias": null,
- "name": "id",
- "args": null,
- "storageKey": null
-};
-return {
- "kind": "Request",
- "fragment": {
- "kind": "Fragment",
- "name": "MembersQuery",
- "type": "Query",
- "metadata": null,
- "argumentDefinitions": [],
- "selections": [
- {
- "kind": "LinkedField",
- "alias": null,
- "name": "user_profile",
- "storageKey": null,
- "args": null,
- "concreteType": "User",
- "plural": false,
- "selections": [
- {
- "kind": "LinkedField",
- "alias": null,
- "name": "team",
- "storageKey": null,
- "args": null,
- "concreteType": "Team",
- "plural": false,
- "selections": [
- {
- "kind": "LinkedField",
- "alias": null,
- "name": "members",
- "storageKey": null,
- "args": null,
- "concreteType": "User",
- "plural": true,
- "selections": [
- (v0/*: any*/),
- (v1/*: any*/),
- (v2/*: any*/),
- (v3/*: any*/),
- (v4/*: any*/),
- (v5/*: any*/)
- ]
- }
- ]
- }
- ]
- }
- ]
- },
- "operation": {
- "kind": "Operation",
- "name": "MembersQuery",
- "argumentDefinitions": [],
- "selections": [
- {
- "kind": "LinkedField",
- "alias": null,
- "name": "user_profile",
- "storageKey": null,
- "args": null,
- "concreteType": "User",
- "plural": false,
- "selections": [
- {
- "kind": "LinkedField",
- "alias": null,
- "name": "team",
- "storageKey": null,
- "args": null,
- "concreteType": "Team",
- "plural": false,
- "selections": [
- {
- "kind": "LinkedField",
- "alias": null,
- "name": "members",
- "storageKey": null,
- "args": null,
- "concreteType": "User",
- "plural": true,
- "selections": [
- (v0/*: any*/),
- (v1/*: any*/),
- (v2/*: any*/),
- (v3/*: any*/),
- (v4/*: any*/),
- (v5/*: any*/),
- (v6/*: any*/)
- ]
- },
- (v6/*: any*/)
- ]
- },
- (v6/*: any*/)
- ]
- }
- ]
- },
- "params": {
- "operationKind": "query",
- "name": "MembersQuery",
- "id": null,
- "text": "query MembersQuery {\n user_profile {\n team {\n members {\n name\n school\n grad_year\n contact\n skills\n experience\n id\n }\n id\n }\n id\n }\n}\n",
- "metadata": {}
- }
-};
-})();
-// prettier-ignore
-(node/*: any*/).hash = 'f3900c2b67de63c1f97f5c341e62ed33';
-module.exports = node;
diff --git a/client/src/components/__generated__/TeamNotificationsQuery.graphql.js b/client/src/components/__generated__/TeamNotificationsQuery.graphql.js
index e0e377cb..dea4a81f 100644
--- a/client/src/components/__generated__/TeamNotificationsQuery.graphql.js
+++ b/client/src/components/__generated__/TeamNotificationsQuery.graphql.js
@@ -1,6 +1,6 @@
/**
* @flow
- * @relayHash c8d6d980ec6cebf22be41e847a1b8831
+ * @relayHash a1f820eb14477e077db63be7ae4d8c39
*/
/* eslint-disable */
@@ -9,7 +9,9 @@
/*::
import type { ConcreteRequest } from 'relay-runtime';
-export type TeamNotificationsQueryVariables = {||};
+export type TeamNotificationsQueryVariables = {|
+ sent?: ?boolean
+|};
export type TeamNotificationsQueryResponse = {|
+team_notifications: $ReadOnlyArray{|
+id: ?string,
@@ -46,8 +48,10 @@ export type TeamNotificationsQuery = {|
/*
-query TeamNotificationsQuery {
- team_notifications {
+query TeamNotificationsQuery(
+ $sent: Boolean
+) {
+ team_notifications(sent: $sent) {
id
message
bio
@@ -81,90 +85,106 @@ query TeamNotificationsQuery {
*/
const node/*: ConcreteRequest*/ = (function(){
-var v0 = {
+var v0 = [
+ {
+ "kind": "LocalArgument",
+ "name": "sent",
+ "type": "Boolean",
+ "defaultValue": null
+ }
+],
+v1 = [
+ {
+ "kind": "Variable",
+ "name": "sent",
+ "variableName": "sent",
+ "type": "Boolean"
+ }
+],
+v2 = {
"kind": "ScalarField",
"alias": null,
"name": "id",
"args": null,
"storageKey": null
},
-v1 = {
+v3 = {
"kind": "ScalarField",
"alias": null,
"name": "message",
"args": null,
"storageKey": null
},
-v2 = {
+v4 = {
"kind": "ScalarField",
"alias": null,
"name": "bio",
"args": null,
"storageKey": null
},
-v3 = {
+v5 = {
"kind": "ScalarField",
"alias": null,
"name": "idea",
"args": null,
"storageKey": null
},
-v4 = {
+v6 = {
"kind": "ScalarField",
"alias": null,
"name": "__typename",
"args": null,
"storageKey": null
},
-v5 = {
+v7 = {
"kind": "ScalarField",
"alias": null,
"name": "name",
"args": null,
"storageKey": null
},
-v6 = {
+v8 = {
"kind": "InlineFragment",
"type": "User",
"selections": [
- (v0/*: any*/),
- (v5/*: any*/)
+ (v2/*: any*/),
+ (v7/*: any*/)
]
},
-v7 = [
- (v4/*: any*/),
+v9 = [
(v6/*: any*/),
+ (v8/*: any*/),
{
"kind": "InlineFragment",
"type": "Team",
"selections": [
- (v5/*: any*/)
+ (v7/*: any*/)
]
}
],
-v8 = {
+v10 = {
"kind": "ScalarField",
"alias": null,
"name": "senderType",
"args": null,
"storageKey": null
},
-v9 = {
+v11 = {
"kind": "ScalarField",
"alias": null,
"name": "resolved",
"args": null,
"storageKey": null
},
-v10 = [
- (v4/*: any*/),
+v12 = [
(v6/*: any*/),
+ (v8/*: any*/),
{
"kind": "InlineFragment",
"type": "Team",
"selections": [
- (v5/*: any*/),
- (v0/*: any*/)
+ (v7/*: any*/),
+ (v2/*: any*/)
]
}
];
@@ -175,21 +195,21 @@ return {
"name": "TeamNotificationsQuery",
"type": "Query",
"metadata": null,
- "argumentDefinitions": [],
+ "argumentDefinitions": (v0/*: any*/),
"selections": [
{
"kind": "LinkedField",
"alias": null,
"name": "team_notifications",
"storageKey": null,
- "args": null,
+ "args": (v1/*: any*/),
"concreteType": "Notification",
"plural": true,
"selections": [
- (v0/*: any*/),
- (v1/*: any*/),
(v2/*: any*/),
(v3/*: any*/),
+ (v4/*: any*/),
+ (v5/*: any*/),
{
"kind": "LinkedField",
"alias": null,
@@ -198,9 +218,9 @@ return {
"args": null,
"concreteType": null,
"plural": false,
- "selections": (v7/*: any*/)
+ "selections": (v9/*: any*/)
},
- (v8/*: any*/),
+ (v10/*: any*/),
{
"kind": "LinkedField",
"alias": null,
@@ -209,9 +229,9 @@ return {
"args": null,
"concreteType": null,
"plural": false,
- "selections": (v7/*: any*/)
+ "selections": (v9/*: any*/)
},
- (v9/*: any*/)
+ (v11/*: any*/)
]
}
]
@@ -219,21 +239,21 @@ return {
"operation": {
"kind": "Operation",
"name": "TeamNotificationsQuery",
- "argumentDefinitions": [],
+ "argumentDefinitions": (v0/*: any*/),
"selections": [
{
"kind": "LinkedField",
"alias": null,
"name": "team_notifications",
"storageKey": null,
- "args": null,
+ "args": (v1/*: any*/),
"concreteType": "Notification",
"plural": true,
"selections": [
- (v0/*: any*/),
- (v1/*: any*/),
(v2/*: any*/),
(v3/*: any*/),
+ (v4/*: any*/),
+ (v5/*: any*/),
{
"kind": "LinkedField",
"alias": null,
@@ -242,9 +262,9 @@ return {
"args": null,
"concreteType": null,
"plural": false,
- "selections": (v10/*: any*/)
+ "selections": (v12/*: any*/)
},
- (v8/*: any*/),
+ (v10/*: any*/),
{
"kind": "LinkedField",
"alias": null,
@@ -253,9 +273,9 @@ return {
"args": null,
"concreteType": null,
"plural": false,
- "selections": (v10/*: any*/)
+ "selections": (v12/*: any*/)
},
- (v9/*: any*/)
+ (v11/*: any*/)
]
}
]
@@ -264,11 +284,11 @@ return {
"operationKind": "query",
"name": "TeamNotificationsQuery",
"id": null,
- "text": "query TeamNotificationsQuery {\n team_notifications {\n id\n message\n bio\n idea\n sender {\n __typename\n ... on User {\n id\n name\n }\n ... on Team {\n name\n id\n }\n }\n senderType\n receiver {\n __typename\n ... on User {\n id\n name\n }\n ... on Team {\n name\n id\n }\n }\n resolved\n }\n}\n",
+ "text": "query TeamNotificationsQuery(\n $sent: Boolean\n) {\n team_notifications(sent: $sent) {\n id\n message\n bio\n idea\n sender {\n __typename\n ... on User {\n id\n name\n }\n ... on Team {\n name\n id\n }\n }\n senderType\n receiver {\n __typename\n ... on User {\n id\n name\n }\n ... on Team {\n name\n id\n }\n }\n resolved\n }\n}\n",
"metadata": {}
}
};
})();
// prettier-ignore
-(node/*: any*/).hash = '2658c0e5a2fcb86fde0960054ab36d7d';
+(node/*: any*/).hash = 'd7a150cf4fc7f3b4d11aaa0bc4b591e0';
module.exports = node;
diff --git a/client/src/components/__generated__/TeamPageQuery.graphql.js b/client/src/components/__generated__/TeamPageQuery.graphql.js
index 7ffe37ea..f9b073f9 100644
--- a/client/src/components/__generated__/TeamPageQuery.graphql.js
+++ b/client/src/components/__generated__/TeamPageQuery.graphql.js
@@ -1,6 +1,6 @@
/**
* @flow
- * @relayHash 6ab7a75ce433c85527ccfb2facf6ada4
+ * @relayHash c4e92d46a7a95e52fa99d1160ba2136c
*/
/* eslint-disable */
@@ -19,6 +19,7 @@ export type TeamPageQueryResponse = {|
+picture: ?string,
+members: ?$ReadOnlyArray{|
+name: ?string,
+ +email: ?string,
+school: ?string,
+grad_year: ?string,
+contact: ?string,
@@ -72,6 +73,7 @@ query TeamPageQuery(
picture
members {
name
+ email
school
grad_year
contact
@@ -175,6 +177,13 @@ v4 = {
"plural": true,
"selections": [
(v2/*: any*/),
+ {
+ "kind": "ScalarField",
+ "alias": null,
+ "name": "email",
+ "args": null,
+ "storageKey": null
+ },
{
"kind": "ScalarField",
"alias": null,
@@ -386,11 +395,11 @@ return {
"operationKind": "query",
"name": "TeamPageQuery",
"id": null,
- "text": "query TeamPageQuery(\n $team_id: String\n) {\n team(team_id: $team_id) {\n id\n name\n picture\n members {\n name\n school\n grad_year\n contact\n skills\n experience\n visible\n uuid\n id\n slackid\n }\n interests\n description\n project_idea\n notifications {\n id\n bio\n idea\n sender {\n __typename\n ... on User {\n id\n name\n }\n ... on Team {\n id\n name\n }\n }\n senderType\n }\n public\n }\n user_profile {\n team {\n id\n }\n id\n }\n}\n",
+ "text": "query TeamPageQuery(\n $team_id: String\n) {\n team(team_id: $team_id) {\n id\n name\n picture\n members {\n name\n email\n school\n grad_year\n contact\n skills\n experience\n visible\n uuid\n id\n slackid\n }\n interests\n description\n project_idea\n notifications {\n id\n bio\n idea\n sender {\n __typename\n ... on User {\n id\n name\n }\n ... on Team {\n id\n name\n }\n }\n senderType\n }\n public\n }\n user_profile {\n team {\n id\n }\n id\n }\n}\n",
"metadata": {}
}
};
})();
// prettier-ignore
-(node/*: any*/).hash = 'cf90cb34f33b89f103e8b9b203c68786';
+(node/*: any*/).hash = '733aca9a2f67c0f8010bf3a1d5d92ad8';
module.exports = node;
diff --git a/client/src/components/__generated__/TeamRequestsSentQuery.graphql.js b/client/src/components/__generated__/TeamRequestsSentQuery.graphql.js
index 5a5e9ec3..8498786b 100644
--- a/client/src/components/__generated__/TeamRequestsSentQuery.graphql.js
+++ b/client/src/components/__generated__/TeamRequestsSentQuery.graphql.js
@@ -1,6 +1,6 @@
/**
* @flow
- * @relayHash 37609fe8c7b13eb8bf27e39e7f825127
+ * @relayHash 99b49c848f2863683af222fa58820450
*/
/* eslint-disable */
@@ -9,9 +9,11 @@
/*::
import type { ConcreteRequest } from 'relay-runtime';
-export type TeamRequestsSentQueryVariables = {||};
+export type TeamRequestsSentQueryVariables = {|
+ sent?: ?boolean
+|};
export type TeamRequestsSentQueryResponse = {|
- +sent_team_notifications: $ReadOnlyArray{|
+ +team_notifications: $ReadOnlyArray{|
+id: ?string,
+message: ?string,
+bio: ?string,
@@ -46,8 +48,10 @@ export type TeamRequestsSentQuery = {|
/*
-query TeamRequestsSentQuery {
- sent_team_notifications {
+query TeamRequestsSentQuery(
+ $sent: Boolean
+) {
+ team_notifications(sent: $sent) {
id
message
bio
@@ -81,90 +85,106 @@ query TeamRequestsSentQuery {
*/
const node/*: ConcreteRequest*/ = (function(){
-var v0 = {
+var v0 = [
+ {
+ "kind": "LocalArgument",
+ "name": "sent",
+ "type": "Boolean",
+ "defaultValue": null
+ }
+],
+v1 = [
+ {
+ "kind": "Variable",
+ "name": "sent",
+ "variableName": "sent",
+ "type": "Boolean"
+ }
+],
+v2 = {
"kind": "ScalarField",
"alias": null,
"name": "id",
"args": null,
"storageKey": null
},
-v1 = {
+v3 = {
"kind": "ScalarField",
"alias": null,
"name": "message",
"args": null,
"storageKey": null
},
-v2 = {
+v4 = {
"kind": "ScalarField",
"alias": null,
"name": "bio",
"args": null,
"storageKey": null
},
-v3 = {
+v5 = {
"kind": "ScalarField",
"alias": null,
"name": "idea",
"args": null,
"storageKey": null
},
-v4 = {
+v6 = {
"kind": "ScalarField",
"alias": null,
"name": "__typename",
"args": null,
"storageKey": null
},
-v5 = {
+v7 = {
"kind": "ScalarField",
"alias": null,
"name": "name",
"args": null,
"storageKey": null
},
-v6 = {
+v8 = {
"kind": "InlineFragment",
"type": "User",
"selections": [
- (v0/*: any*/),
- (v5/*: any*/)
+ (v2/*: any*/),
+ (v7/*: any*/)
]
},
-v7 = [
- (v4/*: any*/),
+v9 = [
(v6/*: any*/),
+ (v8/*: any*/),
{
"kind": "InlineFragment",
"type": "Team",
"selections": [
- (v5/*: any*/)
+ (v7/*: any*/)
]
}
],
-v8 = {
+v10 = {
"kind": "ScalarField",
"alias": null,
"name": "senderType",
"args": null,
"storageKey": null
},
-v9 = {
+v11 = {
"kind": "ScalarField",
"alias": null,
"name": "resolved",
"args": null,
"storageKey": null
},
-v10 = [
- (v4/*: any*/),
+v12 = [
(v6/*: any*/),
+ (v8/*: any*/),
{
"kind": "InlineFragment",
"type": "Team",
"selections": [
- (v5/*: any*/),
- (v0/*: any*/)
+ (v7/*: any*/),
+ (v2/*: any*/)
]
}
];
@@ -175,21 +195,21 @@ return {
"name": "TeamRequestsSentQuery",
"type": "Query",
"metadata": null,
- "argumentDefinitions": [],
+ "argumentDefinitions": (v0/*: any*/),
"selections": [
{
"kind": "LinkedField",
"alias": null,
- "name": "sent_team_notifications",
+ "name": "team_notifications",
"storageKey": null,
- "args": null,
+ "args": (v1/*: any*/),
"concreteType": "Notification",
"plural": true,
"selections": [
- (v0/*: any*/),
- (v1/*: any*/),
(v2/*: any*/),
(v3/*: any*/),
+ (v4/*: any*/),
+ (v5/*: any*/),
{
"kind": "LinkedField",
"alias": null,
@@ -198,9 +218,9 @@ return {
"args": null,
"concreteType": null,
"plural": false,
- "selections": (v7/*: any*/)
+ "selections": (v9/*: any*/)
},
- (v8/*: any*/),
+ (v10/*: any*/),
{
"kind": "LinkedField",
"alias": null,
@@ -209,9 +229,9 @@ return {
"args": null,
"concreteType": null,
"plural": false,
- "selections": (v7/*: any*/)
+ "selections": (v9/*: any*/)
},
- (v9/*: any*/)
+ (v11/*: any*/)
]
}
]
@@ -219,21 +239,21 @@ return {
"operation": {
"kind": "Operation",
"name": "TeamRequestsSentQuery",
- "argumentDefinitions": [],
+ "argumentDefinitions": (v0/*: any*/),
"selections": [
{
"kind": "LinkedField",
"alias": null,
- "name": "sent_team_notifications",
+ "name": "team_notifications",
"storageKey": null,
- "args": null,
+ "args": (v1/*: any*/),
"concreteType": "Notification",
"plural": true,
"selections": [
- (v0/*: any*/),
- (v1/*: any*/),
(v2/*: any*/),
(v3/*: any*/),
+ (v4/*: any*/),
+ (v5/*: any*/),
{
"kind": "LinkedField",
"alias": null,
@@ -242,9 +262,9 @@ return {
"args": null,
"concreteType": null,
"plural": false,
- "selections": (v10/*: any*/)
+ "selections": (v12/*: any*/)
},
- (v8/*: any*/),
+ (v10/*: any*/),
{
"kind": "LinkedField",
"alias": null,
@@ -253,9 +273,9 @@ return {
"args": null,
"concreteType": null,
"plural": false,
- "selections": (v10/*: any*/)
+ "selections": (v12/*: any*/)
},
- (v9/*: any*/)
+ (v11/*: any*/)
]
}
]
@@ -264,11 +284,11 @@ return {
"operationKind": "query",
"name": "TeamRequestsSentQuery",
"id": null,
- "text": "query TeamRequestsSentQuery {\n sent_team_notifications {\n id\n message\n bio\n idea\n sender {\n __typename\n ... on User {\n id\n name\n }\n ... on Team {\n name\n id\n }\n }\n senderType\n receiver {\n __typename\n ... on User {\n id\n name\n }\n ... on Team {\n name\n id\n }\n }\n resolved\n }\n}\n",
+ "text": "query TeamRequestsSentQuery(\n $sent: Boolean\n) {\n team_notifications(sent: $sent) {\n id\n message\n bio\n idea\n sender {\n __typename\n ... on User {\n id\n name\n }\n ... on Team {\n name\n id\n }\n }\n senderType\n receiver {\n __typename\n ... on User {\n id\n name\n }\n ... on Team {\n name\n id\n }\n }\n resolved\n }\n}\n",
"metadata": {}
}
};
})();
// prettier-ignore
-(node/*: any*/).hash = 'a0f663963064ab2d189ad9db8fd29f6a';
+(node/*: any*/).hash = '05bdc59b9613319a5bd0a20195b6c467';
module.exports = node;
diff --git a/package-lock.json b/package-lock.json
index 57955a50..623e1e94 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1044,9 +1044,9 @@
}
},
"@types/express-serve-static-core": {
- "version": "4.17.8",
- "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.8.tgz",
- "integrity": "sha512-1SJZ+R3Q/7mLkOD9ewCBDYD2k0WyZQtWYqF/2VvoNN2/uhI49J9CDN4OAm+wGMA0DbArA4ef27xl4+JwMtGggw==",
+ "version": "4.17.17",
+ "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.17.tgz",
+ "integrity": "sha512-YYlVaCni5dnHc+bLZfY908IG1+x5xuibKZMGv8srKkvtul3wUuanYvpIj9GXXoWkQbaAdR+kgX46IETKUALWNQ==",
"requires": {
"@types/node": "*",
"@types/qs": "*",
diff --git a/package.json b/package.json
index 20b0bdfa..8ed502e0 100644
--- a/package.json
+++ b/package.json
@@ -10,6 +10,7 @@
"build": "gulp build"
},
"dependencies": {
+ "@types/express-serve-static-core": "^4.17.17",
"apollo-server": "^2.16.0",
"apollo-server-express": "^1.4.0",
"bad-words": "^3.0.2",
diff --git a/server/api.graphql b/server/api.graphql
index 02db9d32..75e496bb 100644
--- a/server/api.graphql
+++ b/server/api.graphql
@@ -19,8 +19,7 @@ type Query {
teams(search: String, name: String, picture: String, team_id: String, interests: String, description: String, public: Boolean): [Team!]!
team(team_id: String): Team!
notifications(receiver_type: NotificationType, receiver_id: String): [Notification!]!
- team_notifications: [Notification]!
- sent_team_notifications: [Notification]!
+ team_notifications(sent: Boolean): [Notification]!
}
type Mutation {
diff --git a/server/package-lock.json b/server/package-lock.json
index 8a317955..02e96a28 100644
--- a/server/package-lock.json
+++ b/server/package-lock.json
@@ -5,9 +5,9 @@
"requires": true,
"dependencies": {
"@apollo/protobufjs": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/@apollo/protobufjs/-/protobufjs-1.0.4.tgz",
- "integrity": "sha512-EE3zx+/D/wur/JiLp6VCiw1iYdyy1lCJMf8CGPkLeDt5QJrN4N8tKFx33Ah4V30AUQzMk7Uz4IXKZ1LOj124gA==",
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/@apollo/protobufjs/-/protobufjs-1.0.5.tgz",
+ "integrity": "sha512-ZtyaBH1icCgqwIGb3zrtopV2D5Q8yxibkJzlaViM08eOhTQc7rACdYu0pfORFfhllvdMZ3aq69vifYHszY4gNA==",
"requires": {
"@protobufjs/aspromise": "^1.1.2",
"@protobufjs/base64": "^1.1.2",
@@ -25,9 +25,9 @@
},
"dependencies": {
"@types/node": {
- "version": "10.17.28",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.28.tgz",
- "integrity": "sha512-dzjES1Egb4c1a89C7lKwQh8pwjYmlOAG9dW1pBgxEk57tMrLnssOfEthz8kdkNaBd7lIqQx7APm5+mZ619IiCQ=="
+ "version": "10.17.49",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.49.tgz",
+ "integrity": "sha512-PGaJNs5IZz5XgzwJvL/1zRfZB7iaJ5BydZ8/Picm+lUNYoNO9iVTQkVy5eUh0dZDrx3rBOIs3GCbCRmMuYyqwg=="
}
}
},
@@ -1469,9 +1469,9 @@
}
},
"@types/connect": {
- "version": "3.4.33",
- "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.33.tgz",
- "integrity": "sha512-2+FrkXY4zllzTNfJth7jOqEHC+enpLeGslEhpnTAkg21GkRrWV4SsAtqchtT4YS9/nODBU2/ZfsBY2X4J/dX7A==",
+ "version": "3.4.34",
+ "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.34.tgz",
+ "integrity": "sha512-ePPA/JuI+X0vb+gSWlPKOY0NdNAie/rPUqX2GUPpbZwiKTkSPhjXWuee47E4MtE54QVzGCQMQkAL6JhV2E1+cQ==",
"requires": {
"@types/node": "*"
}
@@ -1497,9 +1497,9 @@
"dev": true
},
"@types/cookies": {
- "version": "0.7.4",
- "resolved": "https://registry.npmjs.org/@types/cookies/-/cookies-0.7.4.tgz",
- "integrity": "sha512-oTGtMzZZAVuEjTwCjIh8T8FrC8n/uwy+PG0yTvQcdZ7etoel7C7/3MSd7qrukENTgQtotG7gvBlBojuVs7X5rw==",
+ "version": "0.7.5",
+ "resolved": "https://registry.npmjs.org/@types/cookies/-/cookies-0.7.5.tgz",
+ "integrity": "sha512-3+TAFSm78O7/bAeYdB8FoYGntuT87vVP9JKuQRL8sRhv9313LP2SpHHL50VeFtnyjIcb3UELddMk5Yt0eOSOkg==",
"requires": {
"@types/connect": "*",
"@types/express": "*",
@@ -1508,9 +1508,9 @@
}
},
"@types/cors": {
- "version": "2.8.7",
- "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.7.tgz",
- "integrity": "sha512-sOdDRU3oRS7LBNTIqwDkPJyq0lpHYcbMTt0TrjzsXbk/e37hcLTH6eZX7CdbDeN0yJJvzw9hFBZkbtCSbk/jAQ==",
+ "version": "2.8.8",
+ "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.8.tgz",
+ "integrity": "sha512-fO3gf3DxU2Trcbr75O7obVndW/X5k8rJNZkLXlQWStTHhP71PkRqjwPIEI0yMnJdg9R9OasjU+Bsr+Hr1xy/0w==",
"requires": {
"@types/express": "*"
}
@@ -1584,14 +1584,21 @@
}
},
"@types/graphql-upload": {
- "version": "8.0.3",
- "resolved": "https://registry.npmjs.org/@types/graphql-upload/-/graphql-upload-8.0.3.tgz",
- "integrity": "sha512-hmLg9pCU/GmxBscg8GCr1vmSoEmbItNNxdD5YH2TJkXm//8atjwuprB+xJBK714JG1dkxbbhp5RHX+Pz1KsCMA==",
+ "version": "8.0.4",
+ "resolved": "https://registry.npmjs.org/@types/graphql-upload/-/graphql-upload-8.0.4.tgz",
+ "integrity": "sha512-0TRyJD2o8vbkmJF8InppFcPVcXKk+Rvlg/xvpHBIndSJYpmDWfmtx/ZAtl4f3jR2vfarpTqYgj8MZuJssSoU7Q==",
"requires": {
"@types/express": "*",
"@types/fs-capacitor": "*",
"@types/koa": "*",
- "graphql": "^14.5.3"
+ "graphql": "^15.3.0"
+ },
+ "dependencies": {
+ "graphql": {
+ "version": "15.4.0",
+ "resolved": "https://registry.npmjs.org/graphql/-/graphql-15.4.0.tgz",
+ "integrity": "sha512-EB3zgGchcabbsU9cFe1j+yxdzKQKAbGUWRb13DsrsMN1yyfmmIq+2+L5MqVWcDCE4V89R5AyUOi7sMOGxdsYtA=="
+ }
}
},
"@types/http-assert": {
@@ -1599,20 +1606,26 @@
"resolved": "https://registry.npmjs.org/@types/http-assert/-/http-assert-1.5.1.tgz",
"integrity": "sha512-PGAK759pxyfXE78NbKxyfRcWYA/KwW17X290cNev/qAsn9eQIxkH4shoNBafH37wewhDG/0p1cHPbK6+SzZjWQ=="
},
+ "@types/http-errors": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-1.8.0.tgz",
+ "integrity": "sha512-2aoSC4UUbHDj2uCsCxcG/vRMXey/m17bC7UwitVm5hn22nI8O8Y9iDpA76Orc+DWkQ4zZrOKEshCqR/jSuXAHA=="
+ },
"@types/keygrip": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@types/keygrip/-/keygrip-1.0.2.tgz",
"integrity": "sha512-GJhpTepz2udxGexqos8wgaBx4I/zWIDPh/KOGEwAqtuGDkOUJu5eFvwmdBX4AmB8Odsr+9pHCQqiAqDL/yKMKw=="
},
"@types/koa": {
- "version": "2.11.3",
- "resolved": "https://registry.npmjs.org/@types/koa/-/koa-2.11.3.tgz",
- "integrity": "sha512-ABxVkrNWa4O/Jp24EYI/hRNqEVRlhB9g09p48neQp4m3xL1TJtdWk2NyNQSMCU45ejeELMQZBYyfstyVvO2H3Q==",
+ "version": "2.11.6",
+ "resolved": "https://registry.npmjs.org/@types/koa/-/koa-2.11.6.tgz",
+ "integrity": "sha512-BhyrMj06eQkk04C97fovEDQMpLpd2IxCB4ecitaXwOKGq78Wi2tooaDOWOFGajPk8IkQOAtMppApgSVkYe1F/A==",
"requires": {
"@types/accepts": "*",
"@types/content-disposition": "*",
"@types/cookies": "*",
"@types/http-assert": "*",
+ "@types/http-errors": "*",
"@types/keygrip": "*",
"@types/koa-compose": "*",
"@types/node": "*"
@@ -1742,9 +1755,9 @@
}
},
"@types/qs": {
- "version": "6.9.4",
- "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.4.tgz",
- "integrity": "sha512-+wYo+L6ZF6BMoEjtf8zB2esQsqdV6WsjRK/GP9WOgLPrq87PbNWgIxS76dS5uvl/QXtHGakZmwTznIfcPXcKlQ=="
+ "version": "6.9.5",
+ "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.5.tgz",
+ "integrity": "sha512-/JHkVHtx/REVG0VVToGRGH2+23hsYLHdyG+GrvoUGlGAd0ErauXDyvHtRI/7H7mzLm+tBCKA7pfcpkQ1lf58iQ=="
},
"@types/qwest": {
"version": "1.7.28",
@@ -1812,9 +1825,9 @@
}
},
"@types/ws": {
- "version": "7.2.6",
- "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.2.6.tgz",
- "integrity": "sha512-Q07IrQUSNpr+cXU4E4LtkSIBPie5GLZyyMC1QtQYRLWz701+XcoVygGUZgvLqElq1nU4ICldMYPnexlBsg3dqQ==",
+ "version": "7.4.0",
+ "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.0.tgz",
+ "integrity": "sha512-Y29uQ3Uy+58bZrFLhX36hcI3Np37nqWE7ky5tjiDoy1GDZnIwVxS0CgF+s+1bXMzjKBFy+fqaRfb708iNzdinw==",
"requires": {
"@types/node": "*"
}
@@ -2144,12 +2157,12 @@
}
},
"apollo-cache-control": {
- "version": "0.11.1",
- "resolved": "https://registry.npmjs.org/apollo-cache-control/-/apollo-cache-control-0.11.1.tgz",
- "integrity": "sha512-6iHa8TkcKt4rx5SKRzDNjUIpCQX+7/FlZwD7vRh9JDnM4VH8SWhpj8fUR3CiEY8Kuc4ChXnOY8bCcMju5KPnIQ==",
+ "version": "0.11.4",
+ "resolved": "https://registry.npmjs.org/apollo-cache-control/-/apollo-cache-control-0.11.4.tgz",
+ "integrity": "sha512-FUKE8ASr8GxVq5rmky/tY8bsf++cleGT591lfLiqnPsP1fo3kAfgRfWA2QRHTCKFNlQxzUhVOEDv+PaysqiOjw==",
"requires": {
"apollo-server-env": "^2.4.5",
- "apollo-server-plugin-base": "^0.9.1"
+ "apollo-server-plugin-base": "^0.10.2"
}
},
"apollo-datasource": {
@@ -2161,37 +2174,6 @@
"apollo-server-env": "^2.4.5"
}
},
- "apollo-engine-reporting": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/apollo-engine-reporting/-/apollo-engine-reporting-2.3.0.tgz",
- "integrity": "sha512-SbcPLFuUZcRqDEZ6mSs8uHM9Ftr8yyt2IEu0JA8c3LNBmYXSLM7MHqFe80SVcosYSTBgtMz8mLJO8orhYoSYZw==",
- "requires": {
- "apollo-engine-reporting-protobuf": "^0.5.2",
- "apollo-graphql": "^0.5.0",
- "apollo-server-caching": "^0.5.2",
- "apollo-server-env": "^2.4.5",
- "apollo-server-errors": "^2.4.2",
- "apollo-server-plugin-base": "^0.9.1",
- "apollo-server-types": "^0.5.1",
- "async-retry": "^1.2.1",
- "uuid": "^8.0.0"
- },
- "dependencies": {
- "uuid": {
- "version": "8.3.0",
- "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.0.tgz",
- "integrity": "sha512-fX6Z5o4m6XsXBdli9g7DtWgAx+osMsRRZFKma1mIUsLCz6vRvv+pz5VNbyu9UEDzpMWulZfvpgb/cmDXVulYFQ=="
- }
- }
- },
- "apollo-engine-reporting-protobuf": {
- "version": "0.5.2",
- "resolved": "https://registry.npmjs.org/apollo-engine-reporting-protobuf/-/apollo-engine-reporting-protobuf-0.5.2.tgz",
- "integrity": "sha512-4wm9FR3B7UvJxcK/69rOiS5CAJPEYKufeRWb257ZLfX7NGFTMqvbc1hu4q8Ch7swB26rTpkzfsftLED9DqH9qg==",
- "requires": {
- "@apollo/protobufjs": "^1.0.3"
- }
- },
"apollo-env": {
"version": "0.6.5",
"resolved": "https://registry.npmjs.org/apollo-env/-/apollo-env-0.6.5.tgz",
@@ -2204,16 +2186,16 @@
},
"dependencies": {
"core-js": {
- "version": "3.6.5",
- "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.5.tgz",
- "integrity": "sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA=="
+ "version": "3.8.1",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.8.1.tgz",
+ "integrity": "sha512-9Id2xHY1W7m8hCl8NkhQn5CufmF/WuR30BTRewvCXc1aZd3kMECwNZ69ndLbekKfakw9Rf2Xyc+QR6E7Gg+obg=="
}
}
},
"apollo-graphql": {
- "version": "0.5.0",
- "resolved": "https://registry.npmjs.org/apollo-graphql/-/apollo-graphql-0.5.0.tgz",
- "integrity": "sha512-YSdF/BKPbsnQpxWpmCE53pBJX44aaoif31Y22I/qKpB6ZSGzYijV5YBoCL5Q15H2oA/v/02Oazh9lbp4ek3eig==",
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/apollo-graphql/-/apollo-graphql-0.6.0.tgz",
+ "integrity": "sha512-BxTf5LOQe649e9BNTPdyCGItVv4Ll8wZ2BKnmiYpRAocYEXAVrQPWuSr3dO4iipqAU8X0gvle/Xu9mSqg5b7Qg==",
"requires": {
"apollo-env": "^0.6.5",
"lodash.sortby": "^4.7.0"
@@ -2240,6 +2222,14 @@
"tslib": "^1.9.3"
}
},
+ "apollo-reporting-protobuf": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/apollo-reporting-protobuf/-/apollo-reporting-protobuf-0.6.1.tgz",
+ "integrity": "sha512-qr4DheFP154PGZsd93SSIS9RkqHnR5b6vT+eCloWjy3UIpY+yZ3cVLlttlIjYvOG4xTJ25XEwcHiAExatQo/7g==",
+ "requires": {
+ "@apollo/protobufjs": "^1.0.3"
+ }
+ },
"apollo-server-caching": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/apollo-server-caching/-/apollo-server-caching-0.5.2.tgz",
@@ -2264,31 +2254,35 @@
}
},
"apollo-server-core": {
- "version": "2.16.1",
- "resolved": "https://registry.npmjs.org/apollo-server-core/-/apollo-server-core-2.16.1.tgz",
- "integrity": "sha512-nuwn5ZBbmzPwDetb3FgiFFJlNK7ZBFg8kis/raymrjd3eBGdNcOyMTJDl6J9673X9Xqp+dXQmFYDW/G3G8S1YA==",
+ "version": "2.19.0",
+ "resolved": "https://registry.npmjs.org/apollo-server-core/-/apollo-server-core-2.19.0.tgz",
+ "integrity": "sha512-2aMKUVPyNbomJQaG2tkpfqvp1Tfgxgkdr7nX5zHudYNSzsPrHw+CcYlCbIVFFI/mTZsjoK9czNq1qerFRxZbJw==",
"requires": {
"@apollographql/apollo-tools": "^0.4.3",
"@apollographql/graphql-playground-html": "1.6.26",
"@types/graphql-upload": "^8.0.0",
"@types/ws": "^7.0.0",
- "apollo-cache-control": "^0.11.1",
+ "apollo-cache-control": "^0.11.4",
"apollo-datasource": "^0.7.2",
- "apollo-engine-reporting": "^2.3.0",
+ "apollo-graphql": "^0.6.0",
+ "apollo-reporting-protobuf": "^0.6.1",
"apollo-server-caching": "^0.5.2",
"apollo-server-env": "^2.4.5",
"apollo-server-errors": "^2.4.2",
- "apollo-server-plugin-base": "^0.9.1",
- "apollo-server-types": "^0.5.1",
- "apollo-tracing": "^0.11.1",
+ "apollo-server-plugin-base": "^0.10.2",
+ "apollo-server-types": "^0.6.1",
+ "apollo-tracing": "^0.12.0",
+ "async-retry": "^1.2.1",
"fast-json-stable-stringify": "^2.0.0",
- "graphql-extensions": "^0.12.4",
+ "graphql-extensions": "^0.12.6",
"graphql-tag": "^2.9.2",
"graphql-tools": "^4.0.0",
"graphql-upload": "^8.0.2",
"loglevel": "^1.6.7",
+ "lru-cache": "^5.0.0",
"sha.js": "^2.4.11",
"subscriptions-transport-ws": "^0.9.11",
+ "uuid": "^8.0.0",
"ws": "^6.0.0"
},
"dependencies": {
@@ -2302,8 +2296,28 @@
"deprecated-decorator": "^0.1.6",
"iterall": "^1.1.3",
"uuid": "^3.1.0"
+ },
+ "dependencies": {
+ "uuid": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
+ "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
+ }
+ }
+ },
+ "lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "requires": {
+ "yallist": "^3.0.2"
}
},
+ "uuid": {
+ "version": "8.3.2",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
+ "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
+ },
"ws": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz",
@@ -2311,6 +2325,11 @@
"requires": {
"async-limiter": "~1.0.0"
}
+ },
+ "yallist": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
}
}
},
@@ -2329,18 +2348,19 @@
"integrity": "sha512-FeGxW3Batn6sUtX3OVVUm7o56EgjxDlmgpTLNyWcLb0j6P8mw9oLNyAm3B+deHA4KNdNHO5BmHS2g1SJYjqPCQ=="
},
"apollo-server-express": {
- "version": "2.16.1",
- "resolved": "https://registry.npmjs.org/apollo-server-express/-/apollo-server-express-2.16.1.tgz",
- "integrity": "sha512-Oq5YNcaMYnRk6jDmA9LWf8oSd2KHDVe7jQ4wtooAvG9FVUD+FaFBgSkytXHMvtifQh2wdF07Ri8uDLMz6IQjTw==",
+ "version": "2.19.0",
+ "resolved": "https://registry.npmjs.org/apollo-server-express/-/apollo-server-express-2.19.0.tgz",
+ "integrity": "sha512-3rgSrTme1SlLoecAYtSa8ThH6vYvz29QecgZCigq5Vdc6bFP2SZrCk0ls6BAdD8OZbVKUtizzRxd0yd/uREPAw==",
"requires": {
"@apollographql/graphql-playground-html": "1.6.26",
"@types/accepts": "^1.3.5",
"@types/body-parser": "1.19.0",
- "@types/cors": "^2.8.4",
+ "@types/cors": "2.8.8",
"@types/express": "4.17.7",
+ "@types/express-serve-static-core": "4.17.13",
"accepts": "^1.3.5",
- "apollo-server-core": "^2.16.1",
- "apollo-server-types": "^0.5.1",
+ "apollo-server-core": "^2.19.0",
+ "apollo-server-types": "^0.6.1",
"body-parser": "^1.18.3",
"cors": "^2.8.4",
"express": "^4.17.1",
@@ -2371,6 +2391,16 @@
"@types/serve-static": "*"
}
},
+ "@types/express-serve-static-core": {
+ "version": "4.17.13",
+ "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.13.tgz",
+ "integrity": "sha512-RgDi5a4nuzam073lRGKTUIaL3eF2+H7LJvJ8eUnCI0wA6SNjXc44DCmWNiTLs/AZ7QlsFWZiw/gTG3nSQGL0fA==",
+ "requires": {
+ "@types/node": "*",
+ "@types/qs": "*",
+ "@types/range-parser": "*"
+ }
+ },
"bytes": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
@@ -2635,30 +2665,30 @@
}
},
"apollo-server-plugin-base": {
- "version": "0.9.1",
- "resolved": "https://registry.npmjs.org/apollo-server-plugin-base/-/apollo-server-plugin-base-0.9.1.tgz",
- "integrity": "sha512-kvrX4Z3FdpjrZdHkyl5iY2A1Wvp4b6KQp00DeZqss7GyyKNUBKr80/7RQgBLEw7EWM7WB19j459xM/TjvW0FKQ==",
+ "version": "0.10.2",
+ "resolved": "https://registry.npmjs.org/apollo-server-plugin-base/-/apollo-server-plugin-base-0.10.2.tgz",
+ "integrity": "sha512-uM5uL1lOxbXdgvt/aEIbgs40fV9xA45Y3Mmh0VtQ/ddqq0MXR5aG92nnf8rM+URarBCUfxKJKaYzJJ/CXAnEdA==",
"requires": {
- "apollo-server-types": "^0.5.1"
+ "apollo-server-types": "^0.6.1"
}
},
"apollo-server-types": {
- "version": "0.5.1",
- "resolved": "https://registry.npmjs.org/apollo-server-types/-/apollo-server-types-0.5.1.tgz",
- "integrity": "sha512-my2cPw+DAb2qVnIuBcsRKGyS28uIc2vjFxa1NpRoJZe9gK0BWUBk7wzXnIzWy3HZ5Er11e/40MPTUesNfMYNVA==",
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/apollo-server-types/-/apollo-server-types-0.6.1.tgz",
+ "integrity": "sha512-IEQ37aYvMLiTUzsySVLOSuvvhxuyYdhI05f3cnH6u2aN1HgGp7vX6bg+U3Ue8wbHfdcifcGIk5UEU+Q+QO6InA==",
"requires": {
- "apollo-engine-reporting-protobuf": "^0.5.2",
+ "apollo-reporting-protobuf": "^0.6.1",
"apollo-server-caching": "^0.5.2",
"apollo-server-env": "^2.4.5"
}
},
"apollo-tracing": {
- "version": "0.11.1",
- "resolved": "https://registry.npmjs.org/apollo-tracing/-/apollo-tracing-0.11.1.tgz",
- "integrity": "sha512-l7g+uILw7v32GA46IRXIx5XXbZhFI96BhSqrGK9yyvfq+NMcvVZrj3kIhRImPGhAjMdV+5biA/jztabElAbDjg==",
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/apollo-tracing/-/apollo-tracing-0.12.0.tgz",
+ "integrity": "sha512-cMUYGE6mOEwb9HDqhf4fiPEo2JMhjPIqEprAQEC57El76avRpRig5NM0bnqMZcYJZR5QmLlNcttNccOwf9WrNg==",
"requires": {
"apollo-server-env": "^2.4.5",
- "apollo-server-plugin-base": "^0.9.1"
+ "apollo-server-plugin-base": "^0.10.2"
}
},
"apollo-upload-client": {
@@ -3494,6 +3524,15 @@
"unset-value": "^1.0.0"
}
},
+ "call-bind": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.0.tgz",
+ "integrity": "sha512-AEXsYIyyDY3MCzbwdhzG3Jx1R0J2wetQyUynn6dYHAO+bg8l1k7jwZtRv4ryryFs7EP+NDlikJlVe59jr0cM2w==",
+ "requires": {
+ "function-bind": "^1.1.1",
+ "get-intrinsic": "^1.0.0"
+ }
+ },
"camel-case": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.1.tgz",
@@ -4361,19 +4400,19 @@
}
},
"es-abstract": {
- "version": "1.17.6",
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz",
- "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==",
+ "version": "1.17.7",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz",
+ "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==",
"requires": {
"es-to-primitive": "^1.2.1",
"function-bind": "^1.1.1",
"has": "^1.0.3",
"has-symbols": "^1.0.1",
- "is-callable": "^1.2.0",
- "is-regex": "^1.1.0",
- "object-inspect": "^1.7.0",
+ "is-callable": "^1.2.2",
+ "is-regex": "^1.1.1",
+ "object-inspect": "^1.8.0",
"object-keys": "^1.1.1",
- "object.assign": "^4.1.0",
+ "object.assign": "^4.1.1",
"string.prototype.trimend": "^1.0.1",
"string.prototype.trimstart": "^1.0.1"
},
@@ -4387,6 +4426,17 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="
+ },
+ "object.assign": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz",
+ "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==",
+ "requires": {
+ "call-bind": "^1.0.0",
+ "define-properties": "^1.1.3",
+ "has-symbols": "^1.0.1",
+ "object-keys": "^1.1.1"
+ }
}
}
},
@@ -5596,6 +5646,23 @@
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz",
"integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w=="
},
+ "get-intrinsic": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.0.2.tgz",
+ "integrity": "sha512-aeX0vrFm21ILl3+JpFFRNe9aUvp6VFZb2/CTbgLb8j75kOhvoNYjt9d8KA/tJG4gSo8nzEDedRl0h7vDmBYRVg==",
+ "requires": {
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3",
+ "has-symbols": "^1.0.1"
+ },
+ "dependencies": {
+ "has-symbols": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
+ "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg=="
+ }
+ }
+ },
"get-stream": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
@@ -5774,13 +5841,13 @@
}
},
"graphql-extensions": {
- "version": "0.12.4",
- "resolved": "https://registry.npmjs.org/graphql-extensions/-/graphql-extensions-0.12.4.tgz",
- "integrity": "sha512-GnR4LiWk3s2bGOqIh6V1JgnSXw2RCH4NOgbCFEWvB6JqWHXTlXnLZ8bRSkCiD4pltv7RHUPWqN/sGh8R6Ae/ag==",
+ "version": "0.12.6",
+ "resolved": "https://registry.npmjs.org/graphql-extensions/-/graphql-extensions-0.12.6.tgz",
+ "integrity": "sha512-EUNw+OIRXYTPxToSoJjhJvS5aGa94KkdkZnL1I9DCZT64/+rzQNeLeGj+goj2RYuYvoQe1Bmcx0CNZ1GqwBhng==",
"requires": {
"@apollographql/apollo-tools": "^0.4.3",
"apollo-server-env": "^2.4.5",
- "apollo-server-types": "^0.5.1"
+ "apollo-server-types": "^0.6.1"
}
},
"graphql-subscriptions": {
@@ -6348,9 +6415,9 @@
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
},
"is-callable": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz",
- "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw=="
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz",
+ "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA=="
},
"is-ci": {
"version": "1.2.1",
@@ -6440,6 +6507,11 @@
"resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz",
"integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI="
},
+ "is-negative-zero": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz",
+ "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w=="
+ },
"is-npm": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz",
@@ -6837,9 +6909,9 @@
"integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg="
},
"loglevel": {
- "version": "1.6.8",
- "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.8.tgz",
- "integrity": "sha512-bsU7+gc9AJ2SqpzxwU3+1fedl8zAntbtC5XYlt3s2j1hJcn2PsXSmgN8TaLG/J1/2mod4+cE/3vNL70/c1RNCA=="
+ "version": "1.7.1",
+ "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.1.tgz",
+ "integrity": "sha512-Hesni4s5UkWkwCGJMQGAh71PaLUmKFM60dHvq0zi/vDhhrzuk+4GgNbTXJ12YYQJn6ZKBDNIjYcuQGKudvqrIw=="
},
"long": {
"version": "4.0.0",
@@ -7608,9 +7680,9 @@
}
},
"object-inspect": {
- "version": "1.8.0",
- "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz",
- "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA=="
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.9.0.tgz",
+ "integrity": "sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw=="
},
"object-keys": {
"version": "1.1.0",
@@ -7618,9 +7690,9 @@
"integrity": "sha512-6OO5X1+2tYkNyNEx6TsCxEqFfRWaqx6EtMiSbGrw8Ob8v9Ne+Hl8rBAgLBZn5wjEz3s/s6U1WXFUFOcxxAwUpg=="
},
"object-path": {
- "version": "0.11.4",
- "resolved": "https://registry.npmjs.org/object-path/-/object-path-0.11.4.tgz",
- "integrity": "sha1-NwrnUvvzfePqcKhhwju6iRVpGUk="
+ "version": "0.11.5",
+ "resolved": "https://registry.npmjs.org/object-path/-/object-path-0.11.5.tgz",
+ "integrity": "sha512-jgSbThcoR/s+XumvGMTMf81QVBmah+/Q7K7YduKeKVWL7N111unR2d6pZZarSk6kY/caeNxUDyxOvMWyzoU2eg=="
},
"object-visit": {
"version": "1.0.1",
@@ -7653,12 +7725,55 @@
}
},
"object.getownpropertydescriptors": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz",
- "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==",
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.1.tgz",
+ "integrity": "sha512-6DtXgZ/lIZ9hqx4GtZETobXLR/ZLaa0aqV0kzbn80Rf8Z2e/XFnhA0I7p07N2wH8bBBltr2xQPi6sbKWAY2Eng==",
"requires": {
+ "call-bind": "^1.0.0",
"define-properties": "^1.1.3",
- "es-abstract": "^1.17.0-next.1"
+ "es-abstract": "^1.18.0-next.1"
+ },
+ "dependencies": {
+ "es-abstract": {
+ "version": "1.18.0-next.1",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz",
+ "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==",
+ "requires": {
+ "es-to-primitive": "^1.2.1",
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3",
+ "has-symbols": "^1.0.1",
+ "is-callable": "^1.2.2",
+ "is-negative-zero": "^2.0.0",
+ "is-regex": "^1.1.1",
+ "object-inspect": "^1.8.0",
+ "object-keys": "^1.1.1",
+ "object.assign": "^4.1.1",
+ "string.prototype.trimend": "^1.0.1",
+ "string.prototype.trimstart": "^1.0.1"
+ }
+ },
+ "has-symbols": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
+ "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg=="
+ },
+ "object-keys": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="
+ },
+ "object.assign": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz",
+ "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==",
+ "requires": {
+ "call-bind": "^1.0.0",
+ "define-properties": "^1.1.3",
+ "has-symbols": "^1.0.1",
+ "object-keys": "^1.1.1"
+ }
+ }
}
},
"object.map": {
@@ -9233,21 +9348,21 @@
}
},
"string.prototype.trimend": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz",
- "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==",
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.3.tgz",
+ "integrity": "sha512-ayH0pB+uf0U28CtjlLvL7NaohvR1amUvVZk+y3DYb0Ey2PUV5zPkkKy9+U1ndVEIXO8hNg18eIv9Jntbii+dKw==",
"requires": {
- "define-properties": "^1.1.3",
- "es-abstract": "^1.17.5"
+ "call-bind": "^1.0.0",
+ "define-properties": "^1.1.3"
}
},
"string.prototype.trimstart": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz",
- "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==",
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.3.tgz",
+ "integrity": "sha512-oBIBUy5lea5tt0ovtOFiEQaBkoBBkyJhZXzJYrSmDo5IUUqbOPvVezuRs/agBIdZ2p2Eo1FD6bD9USyBLfl3xg==",
"requires": {
- "define-properties": "^1.1.3",
- "es-abstract": "^1.17.5"
+ "call-bind": "^1.0.0",
+ "define-properties": "^1.1.3"
}
},
"string_decoder": {
@@ -9643,9 +9758,9 @@
}
},
"typescript": {
- "version": "3.4.1",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.4.1.tgz",
- "integrity": "sha512-3NSMb2VzDQm8oBTLH6Nj55VVtUEpe/rgkIzMir0qVoLyjDZlnMBva0U6vDiV3IH+sl/Yu6oP5QwsAQtHPmDd2Q=="
+ "version": "3.9.7",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.7.tgz",
+ "integrity": "sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw=="
},
"ua-parser-js": {
"version": "0.7.21",
diff --git a/server/package.json b/server/package.json
index 7e59fc38..488c463c 100644
--- a/server/package.json
+++ b/server/package.json
@@ -16,7 +16,7 @@
"@types/mongodb": "^3.1.22",
"@types/oauth": "^0.9.1",
"ajv": "^4.11.2",
- "apollo-server-express": "^2.16.1",
+ "apollo-server-express": "^2.9.12",
"compression": "^1.6.2",
"connect-flash": "^0.1.1",
"cors": "^2.8.5",
@@ -25,7 +25,7 @@
"express-graphql": "^0.7.1",
"express-session": "^1.15.6",
"git-rev-sync": "^1.8.0",
- "graphql": "^14.7.0",
+ "graphql": "^14.5.8",
"graphql-tools": "^6.0.14",
"gulp-copy": "^4.0.1",
"gulp-tslint": "^8.1.4",
@@ -44,7 +44,7 @@
"request": "^2.88.0",
"serve-static": "^1.11.1",
"tslint": "^5.15.0",
- "typescript": "^3.3.3333",
+ "typescript": "^3.7.2",
"uuid": "^3.3.2",
"webpack": "^4.29.6"
},
diff --git a/server/src/app.ts b/server/src/app.ts
index 004830d1..7f221603 100644
--- a/server/src/app.ts
+++ b/server/src/app.ts
@@ -1,821 +1,74 @@
-import fs from "fs";
-import path from "path";
-import express from "express";
-import compression from "compression";
-import morgan from "morgan";
-import passport from "passport";
-import session from "express-session";
-import mongoose from "mongoose";
-
-// import express_graphql from "express-graphql"
-import cors from "cors";
-import dotenv from "dotenv";
-const { ApolloServer, gql } = require("apollo-server-express");
-// import { buildSchema } from "graphql"
-import { GroundTruthStrategy } from "./routes/strategies";
-import { IUser, User, Notification, Team } from "./schema";
-import { userRoutes } from "./routes/user";
-import sendSlackMessage from "./sendSlackMessage";
-
-dotenv.config();
-
-const PORT = 3000;
-const typeDefs = gql`
- ${fs.readFileSync(path.resolve(__dirname, "../api.graphql"), "utf8")}
-`;
-const VERSION_NUMBER = JSON.parse(
- fs.readFileSync(path.resolve(__dirname, "../package.json"), "utf8")
-).version;
-//const VERSION_HASH = require("git-rev-sync").short();
-
-export let app = express();
-
-if (process.env.ISPRODUCTION === "true") {
- app.enable("trust proxy");
-} else {
- console.warn("OAuth callback(s) running in development mode");
-}
-
-app.use(morgan("dev"));
-app.use(compression());
-app.use(cors());
-const session_secret = process.env["SECRET"];
-if (!session_secret) {
- throw new Error("Secret not specified");
-}
-app.use(
- session({
- secret: session_secret,
- saveUninitialized: false,
- resave: true,
- })
-);
-
-app.use(passport.initialize());
-app.use(passport.session());
-
-export function loggedInErr(req, res, next) {
- if (req.user) {
- res.status(200).json({
- success: true,
- });
- next();
- } else {
- res.status(401).json({ error: "User not logged in", success: false });
- return;
- }
-}
-
-const gturl = String(process.env.GROUNDTRUTHURL || "login.hack.gt");
-const groundTruthStrategy = new GroundTruthStrategy(gturl);
-passport.use(groundTruthStrategy);
-passport.serializeUser((user, done) => {
- done(null, user.uuid);
-});
-passport.deserializeUser((id, done) => {
- User.findOne({ uuid: id }, (err, user) => {
- done(err, user!);
- });
-});
-
-let getTeam = async function (parent, args, context, info, req) {
- if (!context._id) {
- throw new Error("User is not logged in!");
- }
- let team = await Team.findById(args.team_id).populate("members");
- if (!team) {
- throw new Error("Team not found!");
- }
- return team;
-};
-let getTeams = async function (parent, args, context, info, req) {
- console.log("getting teams..");
- let teams;
- let search;
- let interests;
- let interestSearch = [] as {}[];
-
- if (args.search) {
- search = '"' + args.search.split(" ").join('" "') + '"';
- }
-
- if (args.interests) {
- interests = args.interests.match(/\w+/g);
- for (let i = 0; i < interests.length; i++) {
- interestSearch.push({
- interests: {
- $elemMatch: { $regex: ".*" + interests[i] + ".*", $options: "i" },
- },
- });
- }
- }
-
- if (search && interests) {
- console.log("search and interest filters applied");
- teams = await Team.find({
- $and: [
- { public: true },
- { $text: { $search: search } },
- { $and: interestSearch },
- ],
- }).populate("members");
- } else if (search) {
- console.log(`searching for ${search}..`);
- teams = await Team.find({
- $and: [{ public: true }, { $text: { $search: search } }],
- }).populate("members");
- } else if (interests) {
- console.log(`interest filter(s) applied: ${interestSearch}`);
- teams = await Team.find({
- $and: [{ public: true }, { $and: interestSearch }],
- }).populate("members");
- } else {
- console.log("no filter applied");
- teams = await Team.find({
- public: true,
- }).populate("members");
- }
-
- if (!teams) {
- return null;
- }
-
- teams.sort(function (a, b) {
- return a.name.toLowerCase() - b.name.toLowerCase();
- });
- return teams;
-};
-
-let getUser = async function (parent, args, context, info, req) {
- if (!context._id) {
- throw new Error("User not logged in");
- }
- let user = await User.findById(args.user_id);
- if (!user) {
- throw new Error("User not found");
- }
- return user;
-};
-
-let getUsers = async function (parent, args, context, info, req) {
- if (!context._id) {
- throw new Error("User not logged in");
- }
- console.log("getting users..");
- let users;
- let search;
- let skills;
- let grad_years;
- let schools;
- let skillSearch = [] as {}[];
- let yearSearch = [] as {}[];
- let schoolSearch = [] as {}[];
-
- if (args.search) {
- search = '"' + args.search.split(" ").join('" "') + '"';
- }
- if (args.skill) {
- skills = args.skill.match(/\w+/g);
- for (let i = 0; i < skills.length; i++) {
- skillSearch.push({
- skills: {
- $elemMatch: { $regex: ".*" + skills[i] + ".*", $options: "i" },
- },
- });
- }
- }
- if (args.grad_year) {
- grad_years = args.grad_year.match(/\w+/g);
- for (let i = 0; i < grad_years.length; i++) {
- yearSearch.push({ grad_year: grad_years[i] });
- }
- }
- if (args.school) {
- schools = args.school.split(",");
- for (let i = 0; i < schools.length; i++) {
- schoolSearch.push({ school: schools[i] });
- }
- }
-
- if (search && skills && grad_years && schools) {
- console.log("all filters applied...");
- users = await User.find({
- $and: [
- { $text: { $search: search } },
- { $and: skillSearch },
- { $or: yearSearch },
- { $or: schoolSearch },
- ],
- visible: 1
- });
- } else if (search && skills && grad_years) {
- console.log("search, skills, and grad year filters applied...");
- users = await User.find({
- $and: [
- { $text: { $search: search } },
- { $and: skillSearch },
- { $or: yearSearch },
- ],
- visible: 1
- });
- } else if (search && skills && schools) {
- console.log("search, skills, and schools filters applied...");
- users = await User.find({
- $and: [
- { $text: { $search: search } },
- { $and: skillSearch },
- { $or: schoolSearch },
- ],
- visible: 1
- });
- } else if (search && grad_years && schools) {
- console.log("searc, grad year, and schools filters applied...");
- users = await User.find({
- $and: [
- { $text: { $search: search } },
- { $or: yearSearch },
- { $or: schoolSearch },
- ],
- visible: 1
- });
- } else if (skills && grad_years && schools) {
- console.log("skills, grad year, and schools filter applied...");
- users = await User.find({
- $and: [{ $and: skillSearch }, { $or: yearSearch }, { $or: schoolSearch }],visible: 1
- }
- );
- } else if (search && skills) {
- console.log("search and skills filters applied...");
- users = await User.find({
- $and: [{ $text: { $search: search } }, { $and: skillSearch }], visible: 1
- });
- } else if (search && grad_years) {
- console.log("search and grad year filters applied...");
- users = await User.find({
- $and: [{ $text: { $search: search } }, { $or: yearSearch }], visible: 1
- });
- } else if (search && schools) {
- console.log("search and schools filters applied...");
- users = await User.find({
- $and: [{ $text: { $search: search } }, { $or: schoolSearch }], visible: 1
- });
- } else if (skills && grad_years) {
- console.log("skill and year filters applied");
- users = await User.find({
- $and: [{ $and: skillSearch }, { $or: yearSearch }], visible: 1
- });
- } else if (skills && schools) {
- console.log("only skill and school filters applied");
- users = await User.find({
- $and: [{ $and: skillSearch }, { $or: schoolSearch }],visible: 1
- });
- } else if (grad_years && schools) {
- console.log("only year and school filters applied");
- users = await User.find({
- $and: [{ $or: yearSearch }, { $or: schoolSearch }], visible: 1
- });
- } else if (search) {
- console.log(`searching for ${search}..`);
- users = await User.find({ $text: { $search: search }, visible: 1 });
- console.log(users);
- } else if (skills) {
- console.log("only skill filter(s) applied");
- users = await User.find({
- $and: skillSearch, visible: 1
- });
- } else if (grad_years) {
- console.log("only year filter(s) applied");
- users = await User.find({
- $or: yearSearch, visible: 1
- });
- } else if (schools) {
- console.log("only school filter(s) applied");
- users = await User.find({
- $or: schoolSearch, visible: 1
- });
- } else {
- console.log("no filters applied");
- users = await User.find({visible: 1});
- }
-
- if (!users) {
- return null;
- }
-
- users = users
- .sort(function (a, b) {
- return a.name.toLowerCase() - b.name.toLowerCase();
- })
- .filter((item) => {
- return item.uuid != context.uuid && !item.team && item.visible == 1;
- });
- return users;
-};
-
-let updateUser = async function (parent, args, context, info, req) {
- console.log(context._id);
- if (!context._id) {
- throw new Error("User not logged in");
- }
- return await User.findByIdAndUpdate(
- context._id,
- { $set: args },
- { new: true }
- );
-};
-
-let updateTeam = async function (parent, args, context, info, req) {
- console.log(context._id);
- if (!context._id) {
- throw new Error("User not logged in");
- }
- let user = await User.findById(context._id).populate("team");
- if (!user) {
- throw new Error("User not found");
- }
- if (!user.team) {
- throw new Error("User not on team");
- }
- return await Team.findByIdAndUpdate(user.team, { $set: args }, { new: true });
-};
-
-let leaveTeam = async function (parent, args, context, info, req) {
- console.log("leaveing team");
-
- if (!context._id) {
- throw new Error("User not logged in");
- }
- if (!context.team) {
- throw new Error("User not on team");
- }
-
- await Team.findByIdAndUpdate(
- context.team,
- {
- $pull: {
- members: context._id,
- },
- },
- async (err, team) => {
- if (err || !team) {
- console.log(err);
- throw new Error("Issue updating team");
- }
- console.log("TTTEAM", team);
- if (team.members.length <= 1) {
- await Team.findByIdAndDelete(context.team);
- }
- }
- );
-
- return await User.findByIdAndUpdate(context._id, {
- team: null,
- });
-};
-
-let getSentTeamNotifications = async function (
- parent,
- args,
- context,
- info,
- req
-) {
- if (!context._id) {
- throw new Error("User not logged in");
- }
- let user = await User.findById(context._id);
- if (!user) {
- throw new Error("User not found");
- }
- if (!user.team) {
- throw new Error("User not on teams");
- }
- return await Notification.find({
- sender: user.team,
- resolved: false,
- }).populate("receiver");
-};
-
-let getUserProfile = async function (parent, args, context, info, req) {
- return await User.findById(context._id).populate("team");
-};
-
-/*
- Accepting a user sending request to team
- */
-let acceptTeamRequest = async function (parent, args, context, info, req) {
- if (!context._id) {
- throw new Error("User not logged in");
- }
- let user = await User.findById(context._id).populate("team");
- if (!user) {
- throw new Error("User not found");
- }
- if (!user.team) {
- throw new Error("User not on team");
- }
- if (user.team.members.length >= 4) {
- throw new Error("Team is full");
- }
- let notification = await Notification.findById(args.notification_id)
- .populate("sender")
- .populate("receiver");
- if (!notification) {
- throw new Error("Notification does not exist");
- }
- if (notification.senderType == "Team") {
- throw new Error("Cannot accept request from a team");
- }
- if (notification.senderType == "User") {
- console.log(
- "TEAM",
- user.team._id.toString(),
- notification.receiver._id.toString()
- );
-
- if (user.team._id.toString() !== notification.receiver._id.toString()) {
- throw new Error("Team does not own notification");
- }
- let requestUser = await User.findById(notification.sender._id);
- if (!requestUser) {
- throw new Error("Notificaton sender not found");
- }
- if (requestUser.team) {
- throw new Error("Sender already on team");
- }
- console.log("here2");
-
- let requestedUserId = requestUser._id;
- console.log(requestedUserId);
- console.log(user.team._id);
- console.log(mongoose.Types.ObjectId.isValid(requestedUserId));
- console.log(mongoose.Types.ObjectId.isValid(user.team._id));
-
- await Team.findByIdAndUpdate(
- user.team._id,
- {
- $push: {
- members: requestedUserId,
- },
- },
- function (err, user) {
- console.log("here");
- console.log(err);
- }
- );
- await User.findByIdAndUpdate(notification.sender._id, {
- team: user.team._id,
- });
- await Notification.updateMany({ sender: notification.sender._id, receiver: notification.receiver._id }, {
- resolved: true,
- });
-
- sendSlackMessage(
- `${
- user!.team!.name
- } has accepted your request. View your new team here: https://teamformation.hack.gt/team/${user.team._id}`,
- requestUser.slackid
- );
- console.log("slack message sent");
- } else {
- throw new Error("Notification invalid");
- }
-};
-
-let acceptUserRequest = async function (parent, args, context, info, req) {
- if (!context._id) {
- throw new Error("User not logged in");
- }
- let user = await User.findById(context._id);
- if (!user) {
- throw new Error("User not found");
- }
-
- let notification = await Notification.findById(args.notification_id)
- .populate("sender")
- .populate("receiver");
- if (!notification) {
- throw new Error("Notification not found");
- }
- console.log("ACCEPT USER REQUEST");
- console.log(notification.receiver._id);
- console.log(user._id);
-
- if (notification.receiver._id.toString() != user._id.toString()) {
- throw new Error("Notification not valid");
- }
- await Notification.findByIdAndUpdate(notification._id, {
- resolved: true,
- });
- if (notification.senderType == "Team") {
- if (user.team) {
- throw new Error("User already on team");
- }
- if (!notification.sender) {
- throw new Error("Team no longer exists");
- }
- if (notification.sender.members.length >= 4) {
- throw new Error("Team is full");
- }
- let team = await Team.findByIdAndUpdate(notification.sender._id, {
- $push: {
- members: user,
- },
- }).populate("members");
- await User.findByIdAndUpdate(context._id, {
- team: notification.sender._id,
- });
- let teamSlackIDs: any = [];
- team!.members.forEach((member) => {
- teamSlackIDs.push(member.slackid);
- });
- var index = teamSlackIDs.indexOf(user.slackid);
- if (index != -1) {
- teamSlackIDs.splice(index, 1);
- }
- teamSlackIDs.forEach((id) => {
- sendSlackMessage(
- `${context.name} has accepted your request. View your team here: https://teamformation.hack.gt/feed`,
- id
- );
- });
- console.log("slack message sent");
- return team;
- } else if (notification.senderType == "User") {
- let user1 = await User.findById(context._id);
- let user2 = await User.findById(notification.sender);
- console.log(user1 + " " + user2);
- if (user1 && user2) {
- if (user1.team) {
- throw new Error("User already on a team!");
- }
- if (user2.team) {
- throw new Error("Requesting user already on team");
- }
- var team = new Team({
- name: "Team " + user1._id + "" + user2._id,
- members: [user1, user2],
- public: true,
- });
- return await team.save(function (err, team) {
- if (err) {
- console.log(err);
- }
- if (!user1) {
- throw new Error("User1 not defined");
- }
- if (!user2) {
- throw new Error("User2 not defined");
- }
- user1.team = team;
- user2.team = team;
- user1.save(function (err) {
- if (err) {
- console.log(err);
- throw new Error(err);
- }
- });
- user2.save(function (err) {
- if (err) {
- console.log(err);
- throw new Error(err);
- }
- });
- sendSlackMessage(
- `${context.name} has accepted your request. View your team here: https://teamformation.hack.gt/feed`,
- user2.slackid
- );
- console.log("slack message sent");
- });
- } else {
- throw new Error("User not defined");
- }
- } else {
- throw new Error("Notification invalid");
- }
-};
-
-let makeUserRequest = async function (parent, args, context, info, req) {
- if (!context._id) {
- throw new Error("User not logged in");
- }
- let notification;
- let receiver_id = args.user_id;
- let receiver = await User.findById(receiver_id);
- let senderName = context.name;
- if (!receiver) {
- throw new Error("Receiver user not found");
- }
- if (receiver.team) {
- throw new Error("Requested user already on team");
- }
- if (!context.team) {
- //if user is not on a team
- notification = new Notification({
- bio: args.bio,
- idea: args.idea,
- senderType: "User",
- receiverType: "User",
- sender: context._id,
- receiver: receiver_id,
- resolved: false,
- });
- } else {
- let team = await Team.findById(context.team);
- if (!team) {
- throw new Error("Team not found");
- }
- notification = new Notification({
- bio: args.bio,
- idea: args.idea,
- senderType: "Team",
- receiverType: "User",
- sender: team._id,
- receiver: receiver_id,
- resolved: false,
- });
- senderName = team.name;
- }
-
- return await notification.save((err, notif) => {
- if (err) {
- throw new Error("Error creating notification: " + notif);
- }
- User.findByIdAndUpdate(receiver_id, {
- $push: {
- notifications: notif,
- },
- });
- sendSlackMessage(
- `You have received a request from ${senderName}. Accept or deny the request here: https://teamformation.hack.gt/feed`,
- receiver!.slackid
- );
- if (!context.team) {
- sendSlackMessage(
- `You have sent a request to ${receiver!.name}`,
- context.slackid
- );
- }
- console.log("slack message sent");
- });
-};
-
-let makeTeamRequest = async function (parent, args, context, info, req) {
- if (!context._id) {
- throw new Error("User not logged in");
- }
- let user = await User.findById(context._id);
- let team_id = args.team_id;
-
- let team = await Team.findById(team_id).populate('members');
-
- console.log("TEAM_ID: ", team_id);
- if (!user) {
- throw new Error("User not found!");
- }
- if (user.team) {
- throw new Error("You are already on a team!");
- }
- let notification = new Notification({
- bio: args.bio,
- idea: args.idea,
- senderType: "User",
- receiverType: "Team",
- sender: user._id,
- receiver: team_id,
- resolved: false,
- });
-
- return await notification.save((err, notif) => {
- if (err) {
- throw new Error("Error creating notification: " + notif);
- }
- Team.findByIdAndUpdate(team_id, {
- $push: {
- notifications: notif,
- },
- });
- let teamSlackIDs: any = [];
- team!.members.forEach((member) => {
- console.log(member.slackid)
- teamSlackIDs.push(member.slackid);
- console.log(member.slackid);
- });
- teamSlackIDs.forEach((id) => {
- sendSlackMessage(
- `You have received a request from ${context.name}. Accept or deny the request here: https://teamformation.hack.gt/team/${team_id}`,
- id
- );
- });
- sendSlackMessage(`You have sent a request to ${team!.name}`, user!.slackid);
- });
-};
-
-let getUserNotifications = async function (parent, args, context, info, req) {
- if (!context._id) {
- throw new Error("User not logged in");
- }
- return await Notification.find({
- receiverType: "User",
- receiver: context._id,
- resolved: false,
- }).populate("sender");
-};
-
-let getTeamNotifications = async function (parent, args, context, info, req) {
- if (!context._id) {
- throw new Error("User not logged in");
- }
- if (!context.team) {
- throw new Error("User not on a team");
- }
- return await Notification.find({
- receiverType: "Team",
- receiver: context.team,
- resolved: false,
- })
- .populate("sender")
- .populate("receiver");
-};
-
-// let createTeam = async function(args) {
-//
-// }
-
-let toggleVisibility = async function (parent, args, context, info, req) {
- return User.findByIdAndUpdate(
- context._id,
- { $bit: { visible: { xor: 1 } } },
- { new: true }
- );
-};
-
-let apiRouter = express.Router();
-
-const resolvers = {
- Source: {
- __resolveType(obj, context, info) {
- if (context.team) {
- return "User";
- }
- if (context._id) {
- return "Team";
- }
- return null;
- },
- },
- Query: {
- users: getUsers,
- user_profile: getUserProfile,
- teams: getTeams,
- team: getTeam,
- notifications: getUserNotifications,
- team_notifications: getTeamNotifications,
- sent_team_notifications: getSentTeamNotifications,
- user: getUser,
- },
- Mutation: {
- toggle_visibility: toggleVisibility,
- update_user: updateUser,
- update_team: updateTeam,
- accept_user_request: acceptUserRequest,
- accept_team_request: acceptTeamRequest,
- make_team_request: makeTeamRequest,
- make_user_request: makeUserRequest,
- leave_team: leaveTeam,
- },
-};
-
-apiRouter.use("/user", userRoutes);
-
-app.use("/api", apiRouter);
-
-const server = new ApolloServer({
- typeDefs,
- resolvers,
- context: ({ req }) => {
- return req.user;
- },
- playground: {
- settings: {
- "editor.theme": "dark",
- "request.credentials": "include",
- },
- },
-});
-
-server.applyMiddleware({ app });
-// app.use('/graphql', bodyParser.json(), graphqlExpress({ schema } as GraphQLServerOptions));
-//
-// app.use('/graphiql', graphiqlExpress({ endpointURL: '/graphql' }));
-
-app.use(express.static(path.join(__dirname, "../../client/build")));
-app.get("*", (request, response) => {
- response.sendFile(path.join(__dirname, "../../client/build", "index.html"));
-});
-
-app.listen(PORT, () => {
- console.log(
- `Team Formation system v${VERSION_NUMBER} started on port ${PORT}`
- );
-});
+import fs from "fs";
+import path from "path";
+import express from "express";
+import compression from "compression";
+import morgan from "morgan";
+
+import mongoose from "mongoose";
+import cors from "cors";
+import dotenv from "dotenv";
+const { ApolloServer } = require("apollo-server-express");
+import { userRoutes } from "./routes/user";
+import resolvers from "./resolvers";
+import typeDefs from "./typeDefs";
+
+
+dotenv.config();
+
+const PORT = 3000;
+const VERSION_NUMBER = JSON.parse(
+ fs.readFileSync(path.resolve(__dirname, "../package.json"), "utf8")
+).version;
+
+export let app = express();
+app.use(morgan("dev"));
+app.use(compression());
+app.use(cors());
+
+import schemaDirectives from "./directives"; // handles auth
+
+
+let apiRouter = express.Router();
+
+apiRouter.use("/user", userRoutes);
+app.use("/api", apiRouter);
+
+const server = new ApolloServer({
+ typeDefs,
+ resolvers,
+ schemaDirectives,
+ context: ({ req }) => {
+ return req.user;
+ },
+ playground: {
+ settings: {
+ "editor.theme": "dark",
+ "request.credentials": "include",
+ },
+ },
+});
+
+server.applyMiddleware({ app });
+
+app.use(express.static(path.join(__dirname, "../../client/build")));
+app.get("*", (request, response) => {
+ response.sendFile(path.join(__dirname, "../../client/build", "index.html"));
+});
+
+const MONGO_URL = String(process.env.MONGO_URL);
+
+(async () => {
+ await mongoose
+ .connect(MONGO_URL, {
+ useMongoClient: false,
+ })
+ .catch((err) => {
+ throw err;
+ });
+})();
+
+app.listen(PORT, () => {
+ console.log(
+ `Team Formation system v${VERSION_NUMBER} started on port ${PORT}`
+ );
+});
diff --git a/server/src/app2.ts b/server/src/app2.ts
new file mode 100644
index 00000000..4d8811ab
--- /dev/null
+++ b/server/src/app2.ts
@@ -0,0 +1,818 @@
+import fs from "fs";
+import path from "path";
+import express from "express";
+import compression from "compression";
+import morgan from "morgan";
+import passport from "passport";
+import session from "express-session";
+import mongoose from "mongoose";
+import cors from "cors";
+import dotenv from "dotenv";
+const { ApolloServer, gql } = require("apollo-server-express");
+import { GroundTruthStrategy } from "./routes/strategies";
+import { IUser, User, Notification, Team } from "./schema";
+import { userRoutes } from "./routes/user";
+import { sendSlackMessage } from "./utils";
+
+dotenv.config();
+
+const PORT = 3000;
+const typeDefs = gql`
+ ${fs.readFileSync(path.resolve(__dirname, "../api.graphql"), "utf8")}
+`;
+const VERSION_NUMBER = JSON.parse(
+ fs.readFileSync(path.resolve(__dirname, "../package.json"), "utf8")
+).version;
+//const VERSION_HASH = require("git-rev-sync").short();
+
+export let app = express();
+
+if (process.env.ISPRODUCTION === "true") {
+ app.enable("trust proxy");
+} else {
+ console.warn("OAuth callback(s) running in development mode");
+}
+
+app.use(morgan("dev"));
+app.use(compression());
+app.use(cors());
+const session_secret = process.env["SECRET"];
+if (!session_secret) {
+ throw new Error("Secret not specified");
+}
+app.use(
+ session({
+ secret: session_secret,
+ saveUninitialized: false,
+ resave: true,
+ })
+);
+
+app.use(passport.initialize());
+app.use(passport.session());
+
+export function loggedInErr(req, res, next) {
+ if (req.user) {
+ res.status(200).json({
+ success: true,
+ });
+ next();
+ } else {
+ res.status(401).json({ error: "User not logged in", success: false });
+ return;
+ }
+}
+
+const gturl = String(process.env.GROUNDTRUTHURL || "login.hack.gt");
+const groundTruthStrategy = new GroundTruthStrategy(gturl);
+passport.use(groundTruthStrategy);
+passport.serializeUser((user, done) => {
+ done(null, user.uuid);
+});
+passport.deserializeUser((id, done) => {
+ User.findOne({ uuid: id }, (err, user) => {
+ done(err, user!);
+ });
+});
+
+let getTeam = async function (parent, args, context, info, req) {
+ if (!context._id) {
+ throw new Error("User is not logged in!");
+ }
+ let team = await Team.findById(args.team_id).populate("members");
+ if (!team) {
+ throw new Error("Team not found!");
+ }
+ return team;
+};
+let getTeams = async function (parent, args, context, info, req) {
+ console.log("getting teams..");
+ let teams;
+ let search;
+ let interests;
+ let interestSearch = [] as {}[];
+
+ if (args.search) {
+ search = '"' + args.search.split(" ").join('" "') + '"';
+ }
+
+ if (args.interests) {
+ interests = args.interests.match(/\w+/g);
+ for (let i = 0; i < interests.length; i++) {
+ interestSearch.push({
+ interests: {
+ $elemMatch: { $regex: ".*" + interests[i] + ".*", $options: "i" },
+ },
+ });
+ }
+ }
+
+ if (search && interests) {
+ console.log("search and interest filters applied");
+ teams = await Team.find({
+ $and: [
+ { public: true },
+ { $text: { $search: search } },
+ { $and: interestSearch },
+ ],
+ }).populate("members");
+ } else if (search) {
+ console.log(`searching for ${search}..`);
+ teams = await Team.find({
+ $and: [{ public: true }, { $text: { $search: search } }],
+ }).populate("members");
+ } else if (interests) {
+ console.log(`interest filter(s) applied: ${interestSearch}`);
+ teams = await Team.find({
+ $and: [{ public: true }, { $and: interestSearch }],
+ }).populate("members");
+ } else {
+ console.log("no filter applied");
+ teams = await Team.find({
+ public: true,
+ }).populate("members");
+ }
+
+ if (!teams) {
+ return null;
+ }
+
+ teams.sort(function (a, b) {
+ return a.name.toLowerCase() - b.name.toLowerCase();
+ });
+ return teams;
+};
+
+let getUser = async function (parent, args, context, info, req) {
+ if (!context._id) {
+ throw new Error("User not logged in");
+ }
+ let user = await User.findById(args.user_id);
+ if (!user) {
+ throw new Error("User not found");
+ }
+ return user;
+};
+
+let getUsers = async function (parent, args, context, info, req) {
+ if (!context._id) {
+ throw new Error("User not logged in");
+ }
+ console.log("getting users..");
+ let users;
+ let search;
+ let skills;
+ let grad_years;
+ let schools;
+ let skillSearch = [] as {}[];
+ let yearSearch = [] as {}[];
+ let schoolSearch = [] as {}[];
+
+ if (args.search) {
+ search = '"' + args.search.split(" ").join('" "') + '"';
+ }
+ if (args.skill) {
+ skills = args.skill.match(/\w+/g);
+ for (let i = 0; i < skills.length; i++) {
+ skillSearch.push({
+ skills: {
+ $elemMatch: { $regex: ".*" + skills[i] + ".*", $options: "i" },
+ },
+ });
+ }
+ }
+ if (args.grad_year) {
+ grad_years = args.grad_year.match(/\w+/g);
+ for (let i = 0; i < grad_years.length; i++) {
+ yearSearch.push({ grad_year: grad_years[i] });
+ }
+ }
+ if (args.school) {
+ schools = args.school.split(",");
+ for (let i = 0; i < schools.length; i++) {
+ schoolSearch.push({ school: schools[i] });
+ }
+ }
+
+ if (search && skills && grad_years && schools) {
+ console.log("all filters applied...");
+ users = await User.find({
+ $and: [
+ { $text: { $search: search } },
+ { $and: skillSearch },
+ { $or: yearSearch },
+ { $or: schoolSearch },
+ ],
+ visible: 1
+ });
+ } else if (search && skills && grad_years) {
+ console.log("search, skills, and grad year filters applied...");
+ users = await User.find({
+ $and: [
+ { $text: { $search: search } },
+ { $and: skillSearch },
+ { $or: yearSearch },
+ ],
+ visible: 1
+ });
+ } else if (search && skills && schools) {
+ console.log("search, skills, and schools filters applied...");
+ users = await User.find({
+ $and: [
+ { $text: { $search: search } },
+ { $and: skillSearch },
+ { $or: schoolSearch },
+ ],
+ visible: 1
+ });
+ } else if (search && grad_years && schools) {
+ console.log("searc, grad year, and schools filters applied...");
+ users = await User.find({
+ $and: [
+ { $text: { $search: search } },
+ { $or: yearSearch },
+ { $or: schoolSearch },
+ ],
+ visible: 1
+ });
+ } else if (skills && grad_years && schools) {
+ console.log("skills, grad year, and schools filter applied...");
+ users = await User.find({
+ $and: [{ $and: skillSearch }, { $or: yearSearch }, { $or: schoolSearch }],visible: 1
+ }
+ );
+ } else if (search && skills) {
+ console.log("search and skills filters applied...");
+ users = await User.find({
+ $and: [{ $text: { $search: search } }, { $and: skillSearch }], visible: 1
+ });
+ } else if (search && grad_years) {
+ console.log("search and grad year filters applied...");
+ users = await User.find({
+ $and: [{ $text: { $search: search } }, { $or: yearSearch }], visible: 1
+ });
+ } else if (search && schools) {
+ console.log("search and schools filters applied...");
+ users = await User.find({
+ $and: [{ $text: { $search: search } }, { $or: schoolSearch }], visible: 1
+ });
+ } else if (skills && grad_years) {
+ console.log("skill and year filters applied");
+ users = await User.find({
+ $and: [{ $and: skillSearch }, { $or: yearSearch }], visible: 1
+ });
+ } else if (skills && schools) {
+ console.log("only skill and school filters applied");
+ users = await User.find({
+ $and: [{ $and: skillSearch }, { $or: schoolSearch }],visible: 1
+ });
+ } else if (grad_years && schools) {
+ console.log("only year and school filters applied");
+ users = await User.find({
+ $and: [{ $or: yearSearch }, { $or: schoolSearch }], visible: 1
+ });
+ } else if (search) {
+ console.log(`searching for ${search}..`);
+ users = await User.find({ $text: { $search: search }, visible: 1 });
+ console.log(users);
+ } else if (skills) {
+ console.log("only skill filter(s) applied");
+ users = await User.find({
+ $and: skillSearch, visible: 1
+ });
+ } else if (grad_years) {
+ console.log("only year filter(s) applied");
+ users = await User.find({
+ $or: yearSearch, visible: 1
+ });
+ } else if (schools) {
+ console.log("only school filter(s) applied");
+ users = await User.find({
+ $or: schoolSearch, visible: 1
+ });
+ } else {
+ console.log("no filters applied");
+ users = await User.find({visible: 1});
+ }
+
+ if (!users) {
+ return null;
+ }
+
+ users = users
+ .sort(function (a, b) {
+ return a.name.toLowerCase() - b.name.toLowerCase();
+ })
+ .filter((item) => {
+ return item.uuid != context.uuid && !item.team && item.visible == 1;
+ });
+ return users;
+};
+
+let updateUser = async function (parent, args, context, info, req) {
+ console.log(context._id);
+ if (!context._id) {
+ throw new Error("User not logged in");
+ }
+ return await User.findByIdAndUpdate(
+ context._id,
+ { $set: args },
+ { new: true }
+ );
+};
+
+let updateTeam = async function (parent, args, context, info, req) {
+ console.log(context._id);
+ if (!context._id) {
+ throw new Error("User not logged in");
+ }
+ let user = await User.findById(context._id).populate("team");
+ if (!user) {
+ throw new Error("User not found");
+ }
+ if (!user.team) {
+ throw new Error("User not on team");
+ }
+ return await Team.findByIdAndUpdate(user.team, { $set: args }, { new: true });
+};
+
+let leaveTeam = async function (parent, args, context, info, req) {
+ console.log("leaveing team");
+
+ if (!context._id) {
+ throw new Error("User not logged in");
+ }
+ if (!context.team) {
+ throw new Error("User not on team");
+ }
+
+ await Team.findByIdAndUpdate(
+ context.team,
+ {
+ $pull: {
+ members: context._id,
+ },
+ },
+ async (err, team) => {
+ if (err || !team) {
+ console.log(err);
+ throw new Error("Issue updating team");
+ }
+ console.log("TTTEAM", team);
+ if (team.members.length <= 1) {
+ await Team.findByIdAndDelete(context.team);
+ }
+ }
+ );
+
+ return await User.findByIdAndUpdate(context._id, {
+ team: null,
+ });
+};
+
+let getSentTeamNotifications = async function (
+ parent,
+ args,
+ context,
+ info,
+ req
+) {
+ if (!context._id) {
+ throw new Error("User not logged in");
+ }
+ let user = await User.findById(context._id);
+ if (!user) {
+ throw new Error("User not found");
+ }
+ if (!user.team) {
+ throw new Error("User not on teams");
+ }
+ return await Notification.find({
+ sender: user.team,
+ resolved: false,
+ }).populate("receiver");
+};
+
+let getUserProfile = async function (parent, args, context, info, req) {
+ return await User.findById(context._id).populate("team");
+};
+
+/*
+ Accepting a user sending request to team
+ */
+let acceptTeamRequest = async function (parent, args, context, info, req) {
+ if (!context._id) {
+ throw new Error("User not logged in");
+ }
+ let user = await User.findById(context._id).populate("team");
+ if (!user) {
+ throw new Error("User not found");
+ }
+ if (!user.team) {
+ throw new Error("User not on team");
+ }
+ if (user.team.members.length >= 4) {
+ throw new Error("Team is full");
+ }
+ let notification = await Notification.findById(args.notification_id)
+ .populate("sender")
+ .populate("receiver");
+ if (!notification) {
+ throw new Error("Notification does not exist");
+ }
+ if (notification.senderType == "Team") {
+ throw new Error("Cannot accept request from a team");
+ }
+ if (notification.senderType == "User") {
+ console.log(
+ "TEAM",
+ user.team._id.toString(),
+ notification.receiver._id.toString()
+ );
+
+ if (user.team._id.toString() !== notification.receiver._id.toString()) {
+ throw new Error("Team does not own notification");
+ }
+ let requestUser = await User.findById(notification.sender._id);
+ if (!requestUser) {
+ throw new Error("Notificaton sender not found");
+ }
+ if (requestUser.team) {
+ throw new Error("Sender already on team");
+ }
+ console.log("here2");
+
+ let requestedUserId = requestUser._id;
+ console.log(requestedUserId);
+ console.log(user.team._id);
+ console.log(mongoose.Types.ObjectId.isValid(requestedUserId));
+ console.log(mongoose.Types.ObjectId.isValid(user.team._id));
+
+ await Team.findByIdAndUpdate(
+ user.team._id,
+ {
+ $push: {
+ members: requestedUserId,
+ },
+ },
+ function (err, user) {
+ console.log("here");
+ console.log(err);
+ }
+ );
+ await User.findByIdAndUpdate(notification.sender._id, {
+ team: user.team._id,
+ });
+ await Notification.updateMany({ sender: notification.sender._id, receiver: notification.receiver._id }, {
+ resolved: true,
+ });
+
+ sendSlackMessage(
+ `${
+ user!.team!.name
+ } has accepted your request. View your new team here: https://teamformation.hack.gt/team/${user.team._id}`,
+ requestUser.slackid
+ );
+ console.log("slack message sent");
+ } else {
+ throw new Error("Notification invalid");
+ }
+};
+
+let acceptUserRequest = async function (parent, args, context, info, req) {
+ if (!context._id) {
+ throw new Error("User not logged in");
+ }
+ let user = await User.findById(context._id);
+ if (!user) {
+ throw new Error("User not found");
+ }
+
+ let notification = await Notification.findById(args.notification_id)
+ .populate("sender")
+ .populate("receiver");
+ if (!notification) {
+ throw new Error("Notification not found");
+ }
+ console.log("ACCEPT USER REQUEST");
+ console.log(notification.receiver._id);
+ console.log(user._id);
+
+ if (notification.receiver._id.toString() != user._id.toString()) {
+ throw new Error("Notification not valid");
+ }
+ await Notification.findByIdAndUpdate(notification._id, {
+ resolved: true,
+ });
+ if (notification.senderType == "Team") {
+ if (user.team) {
+ throw new Error("User already on team");
+ }
+ if (!notification.sender) {
+ throw new Error("Team no longer exists");
+ }
+ if (notification.sender.members.length >= 4) {
+ throw new Error("Team is full");
+ }
+ let team = await Team.findByIdAndUpdate(notification.sender._id, {
+ $push: {
+ members: user,
+ },
+ }).populate("members");
+ await User.findByIdAndUpdate(context._id, {
+ team: notification.sender._id,
+ });
+ let teamSlackIDs: any = [];
+ team!.members.forEach((member) => {
+ teamSlackIDs.push(member.slackid);
+ });
+ var index = teamSlackIDs.indexOf(user.slackid);
+ if (index != -1) {
+ teamSlackIDs.splice(index, 1);
+ }
+ teamSlackIDs.forEach((id) => {
+ sendSlackMessage(
+ `${context.name} has accepted your request. View your team here: https://teamformation.hack.gt/feed`,
+ id
+ );
+ });
+ console.log("slack message sent");
+ return team;
+ } else if (notification.senderType == "User") {
+ let user1 = await User.findById(context._id);
+ let user2 = await User.findById(notification.sender);
+ console.log(user1 + " " + user2);
+ if (user1 && user2) {
+ if (user1.team) {
+ throw new Error("User already on a team!");
+ }
+ if (user2.team) {
+ throw new Error("Requesting user already on team");
+ }
+ var team = new Team({
+ name: "Team " + user1._id + "" + user2._id,
+ members: [user1, user2],
+ public: true,
+ });
+ return await team.save(function (err, team) {
+ if (err) {
+ console.log(err);
+ }
+ if (!user1) {
+ throw new Error("User1 not defined");
+ }
+ if (!user2) {
+ throw new Error("User2 not defined");
+ }
+ user1.team = team;
+ user2.team = team;
+ user1.save(function (err) {
+ if (err) {
+ console.log(err);
+ throw new Error(err);
+ }
+ });
+ user2.save(function (err) {
+ if (err) {
+ console.log(err);
+ throw new Error(err);
+ }
+ });
+ sendSlackMessage(
+ `${context.name} has accepted your request. View your team here: https://teamformation.hack.gt/feed`,
+ user2.slackid
+ );
+ console.log("slack message sent");
+ });
+ } else {
+ throw new Error("User not defined");
+ }
+ } else {
+ throw new Error("Notification invalid");
+ }
+};
+
+let makeUserRequest = async function (parent, args, context, info, req) {
+ if (!context._id) {
+ throw new Error("User not logged in");
+ }
+ let notification;
+ let receiver_id = args.user_id;
+ let receiver = await User.findById(receiver_id);
+ let senderName = context.name;
+ if (!receiver) {
+ throw new Error("Receiver user not found");
+ }
+ if (receiver.team) {
+ throw new Error("Requested user already on team");
+ }
+ if (!context.team) {
+ //if user is not on a team
+ notification = new Notification({
+ bio: args.bio,
+ idea: args.idea,
+ senderType: "User",
+ receiverType: "User",
+ sender: context._id,
+ receiver: receiver_id,
+ resolved: false,
+ });
+ } else {
+ let team = await Team.findById(context.team);
+ if (!team) {
+ throw new Error("Team not found");
+ }
+ notification = new Notification({
+ bio: args.bio,
+ idea: args.idea,
+ senderType: "Team",
+ receiverType: "User",
+ sender: team._id,
+ receiver: receiver_id,
+ resolved: false,
+ });
+ senderName = team.name;
+ }
+
+ return await notification.save((err, notif) => {
+ if (err) {
+ throw new Error("Error creating notification: " + notif);
+ }
+ User.findByIdAndUpdate(receiver_id, {
+ $push: {
+ notifications: notif,
+ },
+ });
+ sendSlackMessage(
+ `You have received a request from ${senderName}. Accept or deny the request here: https://teamformation.hack.gt/feed`,
+ receiver!.slackid
+ );
+ if (!context.team) {
+ sendSlackMessage(
+ `You have sent a request to ${receiver!.name}`,
+ context.slackid
+ );
+ }
+ console.log("slack message sent");
+ });
+};
+
+let makeTeamRequest = async function (parent, args, context, info, req) {
+ if (!context._id) {
+ throw new Error("User not logged in");
+ }
+ let user = await User.findById(context._id);
+ let team_id = args.team_id;
+
+ let team = await Team.findById(team_id).populate('members');
+
+ console.log("TEAM_ID: ", team_id);
+ if (!user) {
+ throw new Error("User not found!");
+ }
+ if (user.team) {
+ throw new Error("You are already on a team!");
+ }
+ let notification = new Notification({
+ bio: args.bio,
+ idea: args.idea,
+ senderType: "User",
+ receiverType: "Team",
+ sender: user._id,
+ receiver: team_id,
+ resolved: false,
+ });
+
+ return await notification.save((err, notif) => {
+ if (err) {
+ throw new Error("Error creating notification: " + notif);
+ }
+ Team.findByIdAndUpdate(team_id, {
+ $push: {
+ notifications: notif,
+ },
+ });
+ let teamSlackIDs: any = [];
+ team!.members.forEach((member) => {
+ console.log(member.slackid)
+ teamSlackIDs.push(member.slackid);
+ console.log(member.slackid);
+ });
+ teamSlackIDs.forEach((id) => {
+ sendSlackMessage(
+ `You have received a request from ${context.name}. Accept or deny the request here: https://teamformation.hack.gt/team/${team_id}`,
+ id
+ );
+ });
+ sendSlackMessage(`You have sent a request to ${team!.name}`, user!.slackid);
+ });
+};
+
+let getUserNotifications = async function (parent, args, context, info, req) {
+ if (!context._id) {
+ throw new Error("User not logged in");
+ }
+ return await Notification.find({
+ receiverType: "User",
+ receiver: context._id,
+ resolved: false,
+ }).populate("sender");
+};
+
+let getTeamNotifications = async function (parent, args, context, info, req) {
+ if (!context._id) {
+ throw new Error("User not logged in");
+ }
+ if (!context.team) {
+ throw new Error("User not on a team");
+ }
+ return await Notification.find({
+ receiverType: "Team",
+ receiver: context.team,
+ resolved: false,
+ })
+ .populate("sender")
+ .populate("receiver");
+};
+
+// let createTeam = async function(args) {
+//
+// }
+
+let toggleVisibility = async function (parent, args, context, info, req) {
+ return User.findByIdAndUpdate(
+ context._id,
+ { $bit: { visible: { xor: 1 } } },
+ { new: true }
+ );
+};
+
+let apiRouter = express.Router();
+
+const resolvers = {
+ Source: {
+ __resolveType(obj, context, info) {
+ if (context.team) {
+ return "User";
+ }
+ if (context._id) {
+ return "Team";
+ }
+ return null;
+ },
+ },
+ Query: {
+ users: getUsers,
+ user_profile: getUserProfile,
+ teams: getTeams,
+ team: getTeam,
+ notifications: getUserNotifications,
+ team_notifications: getTeamNotifications,
+ sent_team_notifications: getSentTeamNotifications,
+ user: getUser,
+ },
+ Mutation: {
+ toggle_visibility: toggleVisibility,
+ update_user: updateUser,
+ update_team: updateTeam,
+ accept_user_request: acceptUserRequest,
+ accept_team_request: acceptTeamRequest,
+ make_team_request: makeTeamRequest,
+ make_user_request: makeUserRequest,
+ leave_team: leaveTeam,
+ },
+};
+
+apiRouter.use("/user", userRoutes);
+
+app.use("/api", apiRouter);
+
+const server = new ApolloServer({
+ typeDefs,
+ resolvers,
+ context: ({ req }) => {
+ return req.user;
+ },
+ playground: {
+ settings: {
+ "editor.theme": "dark",
+ "request.credentials": "include",
+ },
+ },
+});
+
+server.applyMiddleware({ app });
+// app.use('/graphql', bodyParser.json(), graphqlExpress({ schema } as GraphQLServerOptions));
+//
+// app.use('/graphiql', graphiqlExpress({ endpointURL: '/graphql' }));
+
+app.use(express.static(path.join(__dirname, "../../client/build")));
+app.get("*", (request, response) => {
+ response.sendFile(path.join(__dirname, "../../client/build", "index.html"));
+});
+
+app.listen(PORT, () => {
+ console.log(
+ `Team Formation system v${VERSION_NUMBER} started on port ${PORT}`
+ );
+});
diff --git a/server/src/auth.ts b/server/src/auth.ts
new file mode 100644
index 00000000..938bf3e0
--- /dev/null
+++ b/server/src/auth.ts
@@ -0,0 +1,42 @@
+
+const { AuthenticationError } = require("apollo-server-express");
+import { app } from './app'
+import passport from "passport";
+import session from "express-session";
+import { GroundTruthStrategy } from "./routes/strategies";
+import User from "./models/user";
+import { IUser } from "./types/user";
+
+const session_secret = process.env["SECRET"];
+if (!session_secret) {
+ throw new Error("Secret not specified");
+}
+
+app.use(
+ session({
+ secret: session_secret,
+ saveUninitialized: false,
+ resave: true,
+ })
+);
+
+app.use(passport.initialize());
+app.use(passport.session());
+
+const gturl = String(process.env.GROUNDTRUTHURL || "login.hack.gt");
+const groundTruthStrategy = new GroundTruthStrategy(gturl);
+passport.use(groundTruthStrategy);
+passport.serializeUser((user, done) => {
+ done(null, user.uuid);
+});
+passport.deserializeUser((id, done) => {
+ User.findOne({ uuid: id }, (err, user) => {
+ done(err, user!);
+ });
+});
+
+export const ensureSignedIn = (context): void => {
+ if (!context._id) { // check if user's id exists
+ throw new AuthenticationError("You must be signed in.");
+ }
+};
diff --git a/server/src/directives/auth.ts b/server/src/directives/auth.ts
new file mode 100644
index 00000000..b5dc2acf
--- /dev/null
+++ b/server/src/directives/auth.ts
@@ -0,0 +1,20 @@
+// import { SchemaDirectiveVisitor } from 'apollo-server-express'
+const { SchemaDirectiveVisitor } = require("apollo-server-express");
+import { GraphQLField, defaultFieldResolver } from "graphql";
+import { ensureSignedIn } from "../auth";
+
+class AuthDirective extends SchemaDirectiveVisitor {
+ public visitFieldDefinition(field: GraphQLField) {
+ const { resolve = defaultFieldResolver } = field;
+
+ field.resolve = function (...args) {
+ const [, , context] = args;
+
+ ensureSignedIn(context);
+
+ return resolve.apply(this, args);
+ };
+ }
+}
+
+export default AuthDirective;
diff --git a/server/src/directives/index.ts b/server/src/directives/index.ts
new file mode 100644
index 00000000..0d9e083d
--- /dev/null
+++ b/server/src/directives/index.ts
@@ -0,0 +1,5 @@
+import AuthDirective from './auth';
+
+export default {
+ auth: AuthDirective
+}
\ No newline at end of file
diff --git a/server/src/models/index.ts b/server/src/models/index.ts
new file mode 100644
index 00000000..a218d4db
--- /dev/null
+++ b/server/src/models/index.ts
@@ -0,0 +1,6 @@
+
+export { default as User } from './user'
+
+export { default as Team } from './team'
+
+export { default as Notification } from './notification'
\ No newline at end of file
diff --git a/server/src/models/notification.ts b/server/src/models/notification.ts
new file mode 100644
index 00000000..02c0f267
--- /dev/null
+++ b/server/src/models/notification.ts
@@ -0,0 +1,32 @@
+import { model, Schema } from 'mongoose'
+import { INotificationMongoose } from '../types'
+
+const Notification = model("Notification", new Schema({
+ message: String,
+ bio: String,
+ idea: String,
+ senderType: {
+ type: String,
+ required: true,
+ enum: ['Team', 'User']
+ },
+ receiverType: {
+ type: String,
+ required: true,
+ enum: ['Team', 'User']
+ },
+ sender: {
+ type: Schema.Types.ObjectId,
+ required: true,
+ refPath: 'senderType'
+ },
+ receiver: {
+ type: Schema.Types.ObjectId,
+ required: true,
+ refPath: 'receiverType'
+ },
+ resolved: Boolean
+}));
+
+export default Notification
+
diff --git a/server/src/models/team.ts b/server/src/models/team.ts
new file mode 100644
index 00000000..8415cc96
--- /dev/null
+++ b/server/src/models/team.ts
@@ -0,0 +1,43 @@
+import { model, Schema } from 'mongoose'
+import { ITeamMongoose } from '../types'
+
+const TeamSchema = new Schema({
+ name: {
+ required: true,
+ type: String,
+ unique: true
+ },
+ picture: String,
+ members: {
+ required: true,
+ type: [{
+ type: Schema.Types.ObjectId,
+ ref: "User"
+ }]
+ },
+ interests: [String],
+ description: String,
+ project_idea: String,
+ notifications: {
+ type: [{
+ type: Schema.Types.ObjectId,
+ ref: "Notification"
+ }]
+ },
+ public: Boolean
+ },
+ {
+ usePushEach: true
+ }
+);
+
+TeamSchema.index({
+ name: 'text',
+ members: 'text',
+ interests: 'text',
+ description: 'text'
+})
+
+const Team = model("Team", TeamSchema);
+
+export default Team
\ No newline at end of file
diff --git a/server/src/models/user.ts b/server/src/models/user.ts
new file mode 100644
index 00000000..50bce7a7
--- /dev/null
+++ b/server/src/models/user.ts
@@ -0,0 +1,55 @@
+import { model, Schema } from 'mongoose'
+import { IUserMongoose } from '../types'
+
+const UserSchema = new Schema({
+ uuid: {
+ type: String,
+ required: true,
+ index: true,
+ unique: true
+ },
+ email: {
+ type: String,
+ required: true,
+ unique: true
+ },
+ name: {
+ type: String,
+ required: false
+ },
+ school: {
+ type: String,
+ required: false
+ },
+ token: String,
+ grad_year: String,
+ skills: [String],
+ beginner: {
+ type: Boolean,
+ required: false
+ },
+ experience: String,
+ image: String,
+ auth_keys: [String],
+ admin: Boolean,
+ contact: String,
+ contact_method: String,
+ visible: Number,
+ team: {
+ type: Schema.Types.ObjectId,
+ ref: "Team"
+ },
+ slackid: String
+});
+
+UserSchema.index({
+ name: 'text',
+ school: 'text',
+ grad_year: 'text',
+ skills: 'text',
+ experience: 'text'
+});
+
+const User = model("User", UserSchema);
+
+export default User
\ No newline at end of file
diff --git a/server/src/resolvers/index.ts b/server/src/resolvers/index.ts
new file mode 100644
index 00000000..6b7ebcfb
--- /dev/null
+++ b/server/src/resolvers/index.ts
@@ -0,0 +1,6 @@
+import user from './user';
+import team from './team';
+import notification from './notification';
+import source from './source'
+
+export default [source, user, team, notification]
\ No newline at end of file
diff --git a/server/src/resolvers/notification/index.ts b/server/src/resolvers/notification/index.ts
new file mode 100644
index 00000000..ab4cdcf8
--- /dev/null
+++ b/server/src/resolvers/notification/index.ts
@@ -0,0 +1,23 @@
+import {
+ acceptTeamRequest,
+ makeTeamRequest,
+ acceptUserRequest,
+ makeUserRequest,
+} from "./mutations";
+
+import { getTeamNotifications, getUserNotifications } from "./queries";
+
+const resolvers = {
+ Query: {
+ team_notifications: getTeamNotifications,
+ notifications: getUserNotifications,
+ },
+ Mutation: {
+ accept_user_request: acceptUserRequest,
+ accept_team_request: acceptTeamRequest,
+ make_team_request: makeTeamRequest,
+ make_user_request: makeUserRequest,
+ }
+};
+
+export default resolvers;
diff --git a/server/src/resolvers/notification/mutations/acceptTeamRequest.ts b/server/src/resolvers/notification/mutations/acceptTeamRequest.ts
new file mode 100644
index 00000000..8de50cbf
--- /dev/null
+++ b/server/src/resolvers/notification/mutations/acceptTeamRequest.ts
@@ -0,0 +1,87 @@
+import { Team, User, Notification } from "../../../models";
+import {
+ IUserMongoose,
+ INotificationMongoose,
+} from "../../../types";
+import { GraphQLError } from "graphql";
+import { sendSlackMessage } from "../../../utils";
+
+const acceptTeamRequest = async function (
+ parent,
+ args,
+ context,
+ info,
+ req
+): Promise {
+ let user: IUserMongoose | null = await User.findById(context._id).populate(
+ "team"
+ );
+ if (!user) {
+ throw new GraphQLError("User not found");
+ }
+ if (!user.team) {
+ throw new GraphQLError("User not on team");
+ }
+ if (user.team.members.length >= 4) {
+ throw new GraphQLError("Team is full");
+ }
+ let notification = await Notification.findById(args.notification_id)
+ .populate("sender")
+ .populate("receiver");
+ if (!notification) {
+ throw new GraphQLError("Notification does not exist");
+ }
+ if (notification.senderType == "Team") {
+ throw new GraphQLError("Cannot accept request from a team");
+ }
+ if (notification.senderType == "User") {
+ if (user.team._id.toString() !== notification.receiver._id.toString()) {
+ throw new GraphQLError("Team does not own notification");
+ }
+ let requestUser = await User.findById(notification.sender._id);
+ if (!requestUser) {
+ throw new GraphQLError("Notificaton sender not found");
+ }
+ if (requestUser.team) {
+ throw new GraphQLError("Sender already on team");
+ }
+
+ let requestedUserId = requestUser._id;
+
+ await Team.findByIdAndUpdate(
+ user.team._id,
+ {
+ $push: {
+ members: requestedUserId,
+ },
+ },
+ function (err, user) {
+ throw new GraphQLError(err);
+ }
+ );
+ await User.findByIdAndUpdate(notification.sender._id, {
+ team: user.team._id,
+ });
+
+ await Notification.updateMany(
+ { sender: notification.sender._id, receiver: notification.receiver._id },
+ {
+ resolved: true,
+ }
+ );
+
+ sendSlackMessage(
+ `${
+ user!.team!.name
+ } has accepted your request. View your new team here: https://teamformation.hack.gt/team/${
+ user.team._id
+ }`,
+ requestUser.slackid
+ );
+ return notification;
+ } else {
+ throw new Error("Notification invalid");
+ }
+};
+
+export default acceptTeamRequest;
diff --git a/server/src/resolvers/notification/mutations/acceptUserRequest.ts b/server/src/resolvers/notification/mutations/acceptUserRequest.ts
new file mode 100644
index 00000000..d4505461
--- /dev/null
+++ b/server/src/resolvers/notification/mutations/acceptUserRequest.ts
@@ -0,0 +1,131 @@
+import { Team, User, Notification } from "../../../models";
+import {
+ IUserMongoose,
+ ITeamMongoose,
+ INotificationMongoose,
+} from "../../../types";
+import { GraphQLError } from "graphql";
+import { sendSlackMessage } from "../../../utils";
+
+const acceptUserRequest = async function (
+ parent,
+ args,
+ context,
+ info,
+ req
+): Promise {
+ let user = await User.findById(context._id);
+ if (!user) {
+ throw new Error("User not found");
+ }
+
+ let notification: INotificationMongoose | null = await Notification.findById(
+ args.notification_id
+ )
+ .populate("sender")
+ .populate("receiver");
+ if (!notification) {
+ throw new GraphQLError("Notification not found");
+ }
+
+ if (notification.receiver._id.toString() != user._id.toString()) {
+ throw new GraphQLError("Notification not valid");
+ }
+ await Notification.findByIdAndUpdate(notification._id, {
+ resolved: true,
+ });
+ if (notification.senderType == "Team") {
+ if (user.team) {
+ throw new GraphQLError("User already on team");
+ }
+ if (!notification.sender) {
+ throw new GraphQLError("Team no longer exists");
+ }
+ if (notification.sender.members.length >= 4) {
+ throw new GraphQLError("Team is full");
+ }
+ let team = await Team.findByIdAndUpdate(notification.sender._id, {
+ $push: {
+ members: user,
+ },
+ }).populate("members");
+
+ await User.findByIdAndUpdate(context._id, {
+ team: notification.sender._id,
+ });
+
+ let teamSlackIDs: any = [];
+ team!.members.forEach((member) => {
+ teamSlackIDs.push(member.slackid);
+ });
+
+ var index = teamSlackIDs.indexOf(user.slackid);
+ if (index != -1) {
+ teamSlackIDs.splice(index, 1);
+ }
+ teamSlackIDs.forEach((id) => {
+ sendSlackMessage(
+ `${context.name} has accepted your request. View your team here: https://teamformation.hack.gt/feed`,
+ id
+ );
+ });
+ return team;
+ } else if (notification.senderType == "User") {
+ let user1: IUserMongoose | null = await User.findById(context._id);
+ let user2: IUserMongoose | null = await User.findById(notification.sender);
+ if (user1 && user2) {
+ if (user1.team) {
+ throw new Error("User already on a team!");
+ }
+ if (user2.team) {
+ throw new Error("Requesting user already on team");
+ }
+ var team: ITeamMongoose = new Team({
+ name: "Team " + user1._id + "" + user2._id,
+ members: [user1, user2],
+ public: true,
+ });
+
+ if(!team) {
+ throw new GraphQLError("Error creatiing team object");
+ }
+
+ return await team.save(function (err, team) {
+ if (err) {
+ console.log(err);
+ }
+ if (!user1) {
+ throw new Error("User1 not defined");
+ }
+ if (!user2) {
+ throw new Error("User2 not defined");
+ }
+ user1.team = team;
+ user2.team = team;
+ user1.save(function (err) {
+ if (err) {
+ console.log(err);
+ throw new GraphQLError(err);
+ }
+ });
+ user2.save(function (err) {
+ if (err) {
+ console.log(err);
+ throw new GraphQLError(err);
+ }
+ });
+ sendSlackMessage(
+ `${context.name} has accepted your request. View your team here: https://teamformation.hack.gt/feed`,
+ user2.slackid
+ );
+ console.log("slack message sent");
+ });
+ } else {
+ throw new GraphQLError("User not defined");
+ }
+ } else {
+ throw new GraphQLError("Notification invalid");
+ }
+};
+
+export default acceptUserRequest;
diff --git a/server/src/resolvers/notification/mutations/index.ts b/server/src/resolvers/notification/mutations/index.ts
new file mode 100644
index 00000000..a336c4c9
--- /dev/null
+++ b/server/src/resolvers/notification/mutations/index.ts
@@ -0,0 +1,7 @@
+export { default as acceptTeamRequest } from './acceptTeamRequest'
+
+export { default as acceptUserRequest } from './acceptUserRequest'
+
+export { default as makeTeamRequest } from './makeTeamRequest'
+
+export { default as makeUserRequest } from './makeUserRequest'
diff --git a/server/src/resolvers/notification/mutations/makeTeamRequest.ts b/server/src/resolvers/notification/mutations/makeTeamRequest.ts
new file mode 100644
index 00000000..d973a425
--- /dev/null
+++ b/server/src/resolvers/notification/mutations/makeTeamRequest.ts
@@ -0,0 +1,69 @@
+import { Team, User, Notification } from "../../../models";
+import {
+ IUserMongoose,
+ ITeamMongoose,
+ INotificationMongoose,
+} from "../../../types";
+import { GraphQLError } from "graphql";
+import { sendSlackMessage } from "../../../utils";
+
+const makeTeamRequest = async function (
+ parent,
+ args,
+ context,
+ info,
+ req
+): Promise {
+ let user: IUserMongoose | null = await User.findById(context._id);
+ let team_id = args.team_id;
+
+ let team: ITeamMongoose | null = await Team.findById(team_id).populate(
+ "members"
+ );
+
+ if (!user) {
+ throw new GraphQLError("User not found!");
+ }
+ if (user.team) {
+ throw new GraphQLError("You are already on a team!");
+ }
+ let notification: INotificationMongoose = new Notification({
+ bio: args.bio,
+ idea: args.idea,
+ senderType: "User",
+ receiverType: "Team",
+ sender: user._id,
+ receiver: team_id,
+ resolved: false,
+ });
+
+ if(!notification) {
+ throw new GraphQLError("Error creating notification object");
+ }
+
+ return await notification.save((err, notif) => {
+ if (err) {
+ throw new GraphQLError("Error creating notification: " + notif);
+ }
+ Team.findByIdAndUpdate(team_id, {
+ $push: {
+ notifications: notif,
+ },
+ });
+ let teamSlackIDs: any = [];
+ team!.members.forEach((member) => {
+ console.log(member.slackid);
+ teamSlackIDs.push(member.slackid);
+ console.log(member.slackid);
+ });
+ teamSlackIDs.forEach((id) => {
+ sendSlackMessage(
+ `You have received a request from ${context.name}. Accept or deny the request here: https://teamformation.hack.gt/team/${team_id}`,
+ id
+ );
+ });
+ sendSlackMessage(`You have sent a request to ${team!.name}`, user!.slackid);
+ });
+};
+
+export default makeTeamRequest;
diff --git a/server/src/resolvers/notification/mutations/makeUserRequest.ts b/server/src/resolvers/notification/mutations/makeUserRequest.ts
new file mode 100644
index 00000000..9b5bfe92
--- /dev/null
+++ b/server/src/resolvers/notification/mutations/makeUserRequest.ts
@@ -0,0 +1,81 @@
+import { Team, User, Notification } from "../../../models";
+import {
+ IUserMongoose,
+ INotificationMongoose,
+ ITeamMongoose,
+} from "../../../types";
+import { GraphQLError } from "graphql";
+import { sendSlackMessage } from "../../../utils";
+
+const makeUserRequest = async function (
+ parent,
+ args,
+ context,
+ info,
+ req
+): Promise {
+ let notification: INotificationMongoose;
+ let receiver_id = args.user_id;
+ let receiver: IUserMongoose | null = await User.findById(receiver_id);
+ let senderName = context.name;
+ if (!receiver) {
+ throw new GraphQLError("Receiver user not found");
+ }
+ if (receiver.team) {
+ throw new GraphQLError("Requested user already on team");
+ }
+ if (!context.team) {
+ //if user is not on a team
+ notification = new Notification({
+ bio: args.bio,
+ idea: args.idea,
+ senderType: "User",
+ receiverType: "User",
+ sender: context._id,
+ receiver: receiver_id,
+ resolved: false,
+ });
+ } else {
+ let team: ITeamMongoose | null = await Team.findById(context.team);
+ if (!team) {
+ throw new GraphQLError("Team not found");
+ }
+ notification = new Notification({
+ bio: args.bio,
+ idea: args.idea,
+ senderType: "Team",
+ receiverType: "User",
+ sender: team._id,
+ receiver: receiver_id,
+ resolved: false,
+ });
+ senderName = team.name;
+ }
+
+ if(!notification) {
+ throw new GraphQLError("Error creating notification object");
+ }
+
+ return await notification.save((err, notif) => {
+ if (err) {
+ throw new GraphQLError("Error creating notification: " + notif);
+ }
+ User.findByIdAndUpdate(receiver_id, {
+ $push: {
+ notifications: notif,
+ },
+ });
+ sendSlackMessage(
+ `You have received a request from ${senderName}. Accept or deny the request here: https://teamformation.hack.gt/feed`,
+ receiver!.slackid
+ );
+ if (!context.team) {
+ sendSlackMessage(
+ `You have sent a request to ${receiver!.name}`,
+ context.slackid
+ );
+ }
+ });
+};
+
+export default makeUserRequest;
diff --git a/server/src/resolvers/notification/queries/getTeamNotifications.ts b/server/src/resolvers/notification/queries/getTeamNotifications.ts
new file mode 100644
index 00000000..6b1f700a
--- /dev/null
+++ b/server/src/resolvers/notification/queries/getTeamNotifications.ts
@@ -0,0 +1,30 @@
+import { Notification } from "../../../models";
+import { GraphQLError } from "graphql";
+import { INotificationMongoose } from "../../../types";
+
+const getTeamNotifications = async function (
+ parent,
+ args,
+ context,
+ info,
+ req
+): Promise {
+ if (!context.team) {
+ throw new GraphQLError("User not on a team");
+ }
+
+ if (args.sent) {
+ return await Notification.find({
+ sender: context.team,
+ resolved: false,
+ }).populate("receiver");
+ }
+
+ return await Notification.find({
+ receiverType: "Team",
+ receiver: context.team,
+ resolved: false,
+ }).populate("sender");
+};
+
+export default getTeamNotifications;
diff --git a/server/src/resolvers/notification/queries/getUserNotifications.ts b/server/src/resolvers/notification/queries/getUserNotifications.ts
new file mode 100644
index 00000000..602a2484
--- /dev/null
+++ b/server/src/resolvers/notification/queries/getUserNotifications.ts
@@ -0,0 +1,18 @@
+import { Notification } from "../../../models";
+import { INotificationMongoose } from "../../../types";
+
+const getUserNotifications = async function (
+ parent,
+ args,
+ context,
+ info,
+ req
+): Promise {
+ return await Notification.find({
+ receiverType: "User",
+ receiver: context._id,
+ resolved: false,
+ }).populate("sender");
+};
+
+export default getUserNotifications;
diff --git a/server/src/resolvers/notification/queries/index.ts b/server/src/resolvers/notification/queries/index.ts
new file mode 100644
index 00000000..7bb4979b
--- /dev/null
+++ b/server/src/resolvers/notification/queries/index.ts
@@ -0,0 +1,3 @@
+export { default as getTeamNotifications } from './getTeamNotifications'
+
+export { default as getUserNotifications } from './getUserNotifications'
\ No newline at end of file
diff --git a/server/src/resolvers/source/index.ts b/server/src/resolvers/source/index.ts
new file mode 100644
index 00000000..978cb8ee
--- /dev/null
+++ b/server/src/resolvers/source/index.ts
@@ -0,0 +1,15 @@
+const resolvers = {
+ Source: {
+ __resolveType(obj, context, info) {
+ if (context.team) {
+ return "User";
+ }
+ if (context._id) {
+ return "Team";
+ }
+ return null;
+ },
+ },
+};
+
+export default resolvers;
diff --git a/server/src/resolvers/team/index.ts b/server/src/resolvers/team/index.ts
new file mode 100644
index 00000000..f106f586
--- /dev/null
+++ b/server/src/resolvers/team/index.ts
@@ -0,0 +1,15 @@
+import { updateTeam, leaveTeam } from './mutations'
+import { getTeam, getTeams } from './queries';
+
+const resolvers = {
+ Query: {
+ teams: getTeams,
+ team: getTeam
+ },
+ Mutation: {
+ update_team: updateTeam,
+ leave_team: leaveTeam
+ }
+}
+
+export default resolvers
\ No newline at end of file
diff --git a/server/src/resolvers/team/mutations/index.ts b/server/src/resolvers/team/mutations/index.ts
new file mode 100644
index 00000000..f34df412
--- /dev/null
+++ b/server/src/resolvers/team/mutations/index.ts
@@ -0,0 +1,3 @@
+export { default as updateTeam } from './updateTeam'
+
+export { default as leaveTeam } from './leaveTeam'
diff --git a/server/src/resolvers/team/mutations/leaveTeam.ts b/server/src/resolvers/team/mutations/leaveTeam.ts
new file mode 100644
index 00000000..f28a0ce6
--- /dev/null
+++ b/server/src/resolvers/team/mutations/leaveTeam.ts
@@ -0,0 +1,38 @@
+import { Team, User } from "../../../models";
+import { GraphQLError } from "graphql";
+import { IUserMongoose } from "../../../types";
+
+const leaveTeam = async function (
+ parent,
+ args,
+ context,
+ info,
+ req
+): Promise {
+ if (!context.team) {
+ throw new GraphQLError("User not on team");
+ }
+
+ await Team.findByIdAndUpdate(
+ context.team,
+ {
+ $pull: {
+ members: context._id,
+ },
+ },
+ async (err, team) => {
+ if (err || !team) {
+ throw new GraphQLError("Issue updating team");
+ }
+ if (team.members.length <= 1) {
+ await Team.findByIdAndDelete(context.team);
+ }
+ }
+ );
+
+ return await User.findByIdAndUpdate(context._id, {
+ team: null,
+ });
+};
+
+export default leaveTeam;
diff --git a/server/src/resolvers/team/mutations/updateTeam.ts b/server/src/resolvers/team/mutations/updateTeam.ts
new file mode 100644
index 00000000..a4626e90
--- /dev/null
+++ b/server/src/resolvers/team/mutations/updateTeam.ts
@@ -0,0 +1,23 @@
+import { Team, User } from "../../../models";
+import { IUserMongoose, ITeamMongoose } from "../../../types";
+
+const updateTeam = async function (
+ parent,
+ args,
+ context,
+ info,
+ req
+): Promise {
+ let user: IUserMongoose | null = await User.findById(context._id).populate(
+ "team"
+ );
+ if (!user) {
+ throw new Error("User not found");
+ }
+ if (!user.team) {
+ throw new Error("User not on team");
+ }
+ return await Team.findByIdAndUpdate(user.team, { $set: args }, { new: true });
+}; // consider taking in team-id instead of automatically using logged in user's team id
+
+export default updateTeam;
diff --git a/server/src/resolvers/team/queries/getTeam.ts b/server/src/resolvers/team/queries/getTeam.ts
new file mode 100644
index 00000000..6b6d5731
--- /dev/null
+++ b/server/src/resolvers/team/queries/getTeam.ts
@@ -0,0 +1,21 @@
+import { Team } from "../../../models";
+import { GraphQLError } from "graphql";
+import { ITeamMongoose } from "../../../types";
+
+const getTeam = async function (
+ parent,
+ args,
+ context,
+ info,
+ req
+): Promise {
+ let team: ITeamMongoose | null = await Team.findById(args.team_id).populate(
+ "members"
+ );
+ if (!team) {
+ throw new GraphQLError("Team not found!");
+ }
+ return team;
+};
+
+export default getTeam;
diff --git a/server/src/resolvers/team/queries/getTeams.ts b/server/src/resolvers/team/queries/getTeams.ts
new file mode 100644
index 00000000..adea64bf
--- /dev/null
+++ b/server/src/resolvers/team/queries/getTeams.ts
@@ -0,0 +1,44 @@
+import { Team } from "../../../models";
+import { ITeamMongoose } from "../../../types";
+
+const getTeams = async function (
+ parent,
+ args,
+ context,
+ info,
+ req
+): Promise {
+ let teams: ITeamMongoose[];
+ let search: String;
+ let interests: String[];
+ let interestSearch = [] as {}[];
+ let andQuery = [] as {}[];
+ if (args.search) {
+ search = '"' + args.search.split(" ").join('" "') + '"';
+ andQuery.push({ $text: { $search: search } });
+ }
+
+ if (args.interests) {
+ interests = args.interests.match(/\w+/g);
+ interestSearch = interests.map((interest) => {
+ return {
+ interests: {
+ $elemMatch: { $regex: ".*" + interest + ".*", $options: "i" },
+ },
+ };
+ });
+ andQuery.push({ $and: interestSearch });
+ }
+
+ teams = await Team.find({
+ $and: [{ public: true }, ...andQuery],
+ }).populate("members");
+
+ teams.sort(function (a, b) {
+ return a.name.toLowerCase() < b.name.toLowerCase() ? 1 : -1;
+ });
+
+ return teams;
+};
+
+export default getTeams;
diff --git a/server/src/resolvers/team/queries/index.ts b/server/src/resolvers/team/queries/index.ts
new file mode 100644
index 00000000..bdfd7dde
--- /dev/null
+++ b/server/src/resolvers/team/queries/index.ts
@@ -0,0 +1,3 @@
+export { default as getTeam } from './getTeam'
+
+export { default as getTeams } from './getTeams'
diff --git a/server/src/resolvers/user/index.ts b/server/src/resolvers/user/index.ts
new file mode 100644
index 00000000..275a0170
--- /dev/null
+++ b/server/src/resolvers/user/index.ts
@@ -0,0 +1,15 @@
+import { updateUser } from './mutations'
+import { getUser, getUserProfile, getUsers } from './queries';
+
+const resolvers = {
+ Query: {
+ users: getUsers,
+ user_profile: getUserProfile,
+ user: getUser,
+ },
+ Mutation: {
+ update_user: updateUser,
+ }
+}
+
+export default resolvers
\ No newline at end of file
diff --git a/server/src/resolvers/user/mutations/index.ts b/server/src/resolvers/user/mutations/index.ts
new file mode 100644
index 00000000..de532ea1
--- /dev/null
+++ b/server/src/resolvers/user/mutations/index.ts
@@ -0,0 +1 @@
+export { default as updateUser } from './updateUser'
diff --git a/server/src/resolvers/user/mutations/updateUser.ts b/server/src/resolvers/user/mutations/updateUser.ts
new file mode 100644
index 00000000..a749cfed
--- /dev/null
+++ b/server/src/resolvers/user/mutations/updateUser.ts
@@ -0,0 +1,18 @@
+import { User } from "../../../models";
+import { IUserMongoose } from "../../../types";
+
+const updateUser = async function (
+ parent,
+ args,
+ context,
+ info,
+ req
+): Promise {
+ return await User.findByIdAndUpdate(
+ context._id,
+ { $set: args },
+ { new: true }
+ );
+};
+
+export default updateUser;
diff --git a/server/src/resolvers/user/queries/getUser.ts b/server/src/resolvers/user/queries/getUser.ts
new file mode 100644
index 00000000..14bbf1c0
--- /dev/null
+++ b/server/src/resolvers/user/queries/getUser.ts
@@ -0,0 +1,19 @@
+import { User } from "../../../models";
+import { IUserMongoose } from "../../../types";
+import { GraphQLError } from 'graphql';
+
+const getUser = async function (
+ parent,
+ args,
+ context,
+ info,
+ req
+): Promise {
+ let user = await User.findById(args.user_id);
+ if (!user) {
+ throw new GraphQLError("User not found");
+ }
+ return user;
+};
+
+export default getUser;
diff --git a/server/src/resolvers/user/queries/getUserProfile.ts b/server/src/resolvers/user/queries/getUserProfile.ts
new file mode 100644
index 00000000..49dc2756
--- /dev/null
+++ b/server/src/resolvers/user/queries/getUserProfile.ts
@@ -0,0 +1,14 @@
+import { User } from "../../../models";
+import { IUserMongoose } from "../../../types";
+
+const getUserProfile = async function (
+ parent,
+ args,
+ context,
+ info,
+ req
+): Promise {
+ return await User.findById(context._id).populate("team");
+};
+
+export default getUserProfile;
diff --git a/server/src/resolvers/user/queries/getUsers.ts b/server/src/resolvers/user/queries/getUsers.ts
new file mode 100644
index 00000000..7613bac6
--- /dev/null
+++ b/server/src/resolvers/user/queries/getUsers.ts
@@ -0,0 +1,72 @@
+import { IUserMongoose } from "../../../types";
+import { User } from "../../../models"
+
+const getUsers = async function (
+ parent,
+ args,
+ context,
+ info,
+ req
+): Promise {
+ let users: IUserMongoose[];
+ let search: String;
+ let skills: String[];
+ let grad_years: String[];
+ let schools: String[];
+ let skillSearch = [] as {}[];
+ let yearSearch = [] as {}[];
+ let schoolSearch = [] as {}[];
+
+ let andQuery = [] as any;
+ console.log(args)
+ if (args.search) {
+ search = '"' + args.search.split(" ").join('" "') + '"';
+ andQuery.push({ $text: { $search: search } });
+ }
+ if (args.skill) {
+ skills = args.skill.match(/\w+/g);
+ for (let i = 0; i < skills.length; i++) {
+ skillSearch.push({
+ skills: {
+ $elemMatch: { $regex: ".*" + skills[i] + ".*", $options: "i" },
+ },
+ });
+ }
+ andQuery.push({ $and: skillSearch });
+ }
+ if (args.grad_year) {
+ grad_years = args.grad_year.match(/\w+/g);
+ for (let i = 0; i < grad_years.length; i++) {
+ yearSearch.push({ grad_year: grad_years[i] });
+ }
+ andQuery.push({ $or: yearSearch });
+ }
+ if (args.school) {
+ schools = args.school.split(",");
+ for (let i = 0; i < schools.length; i++) {
+ schoolSearch.push({ school: schools[i] });
+ }
+ andQuery.push({ $or: schoolSearch });
+ }
+ console.log(andQuery)
+ if(andQuery.length > 0) {
+ users = await User.find({
+ $and: andQuery,
+ visible: 1,
+ });
+ } else {
+ users = await User.find({ visible: 1 });
+ }
+
+ users = users
+ .sort(function (a, b) {
+ return a.name.toLowerCase() < b.name.toLowerCase() ? 1 : -1;
+ })
+ .filter((item) => {
+ return item.uuid != context.uuid && !item.team && item.visible == 1;
+ });
+
+ return users;
+};
+
+export default getUsers;
diff --git a/server/src/resolvers/user/queries/index.ts b/server/src/resolvers/user/queries/index.ts
new file mode 100644
index 00000000..a0052d2f
--- /dev/null
+++ b/server/src/resolvers/user/queries/index.ts
@@ -0,0 +1,5 @@
+export { default as getUser } from './getUser'
+
+export { default as getUsers } from './getUsers'
+
+export { default as getUserProfile } from './getUserProfile'
diff --git a/server/src/routes/strategies.ts b/server/src/routes/strategies.ts
index f0582fff..ecc1527d 100644
--- a/server/src/routes/strategies.ts
+++ b/server/src/routes/strategies.ts
@@ -4,7 +4,9 @@ import { Strategy as OAuthStrategy } from "passport-oauth2";
import dotenv from "dotenv"
import request from "request"
import { Request } from "express";
-import { createNew, IUser, User } from "../schema";
+import { User } from "../models"
+import { createNew, IUser } from "../types";
+import mongoose from 'mongoose';
dotenv.config()
@@ -74,11 +76,14 @@ export class GroundTruthStrategy extends OAuthStrategy {
}
protected static async passportCallback(req: Request, accessToken: string, refreshToken: string, profile: IProfile, done: PassportDone) {
+ console.log(mongoose.connection.readyState);
+
console.log(profile)
+ console.log("hi")
let user = await User.findOne({ uuid: profile.uuid });
const GRAPHQLURL = process.env.GRAPHQLURL || 'https://registration.hack.gt/graphql'
-
+ console.log("82 here")
if (!user) {
let confirmed = false;
const query = `
@@ -110,6 +115,7 @@ export class GroundTruthStrategy extends OAuthStrategy {
if (JSON.parse(body).data.search_user.users.length > 0) {
confirmed = JSON.parse(body).data.search_user.users[0].confirmed;
}
+ console.log("requesting...")
if (!process.env.ISPRODUCTION || confirmed) {
console.log("here")
user = createNew(User, {
diff --git a/server/src/routes/user.ts b/server/src/routes/user.ts
index aee326a7..498cef2f 100644
--- a/server/src/routes/user.ts
+++ b/server/src/routes/user.ts
@@ -2,7 +2,8 @@ import express from "express";
import request from "request"
import passport from "passport";
import { createLink, AuthenticateOptions } from "./strategies"
-import { IUser, User } from "../schema";
+import { User } from "../models";
+import { IUser } from "../types";
export let userRoutes = express.Router();
userRoutes.route("/login").get((req, response, next) => {
diff --git a/server/src/typeDefs/index.ts b/server/src/typeDefs/index.ts
new file mode 100644
index 00000000..ec711a49
--- /dev/null
+++ b/server/src/typeDefs/index.ts
@@ -0,0 +1,6 @@
+import user from './user'
+import team from './team'
+import notification from './notification'
+import root from './root'
+
+export default [root, user, team, notification]
\ No newline at end of file
diff --git a/server/src/typeDefs/notification.ts b/server/src/typeDefs/notification.ts
new file mode 100644
index 00000000..4c98f395
--- /dev/null
+++ b/server/src/typeDefs/notification.ts
@@ -0,0 +1,28 @@
+const { gql } = require("apollo-server-express");
+
+export default gql`
+ extend type Query {
+ notifications(receiver_id: String): [Notification!]! @auth
+ team_notifications(sent: Boolean): [Notification]! @auth
+ }
+
+ extend type Mutation {
+ accept_team_request(notification_id: String): Team @auth
+ accept_user_request(notification_id: String): Team @auth
+ make_team_request(team_id: String, user_id: String, bio: String, idea: String): Notification @auth
+ make_user_request(user_id: String, bio: String, idea: String): Notification @auth
+ }
+
+ union Source = User | Team
+
+ type Notification {
+ id: ID
+ message: String
+ bio: String
+ idea: String
+ sender: Source
+ senderType: String
+ receiver: Source
+ resolved: Boolean
+ }
+`
\ No newline at end of file
diff --git a/server/src/typeDefs/root.ts b/server/src/typeDefs/root.ts
new file mode 100644
index 00000000..0d3d8b0a
--- /dev/null
+++ b/server/src/typeDefs/root.ts
@@ -0,0 +1,12 @@
+import { gql } from 'apollo-server-express'
+
+export default gql`
+ directive @auth on FIELD_DEFINITION
+
+ type Query {
+ _: String
+ }
+ type Mutation {
+ _: String
+ }
+`
\ No newline at end of file
diff --git a/server/src/typeDefs/team.ts b/server/src/typeDefs/team.ts
new file mode 100644
index 00000000..7ec4500e
--- /dev/null
+++ b/server/src/typeDefs/team.ts
@@ -0,0 +1,25 @@
+const { gql } = require("apollo-server-express");
+
+export default gql`
+ extend type Query {
+ teams(search: String, name: String, picture: String, team_id: String, interests: String, description: String, public: Boolean): [Team!]! @auth
+ team(team_id: String): Team! @auth
+ }
+
+ extend type Mutation {
+ update_team(name: String, picture: String, interests: [String], description: String, public: Boolean, project_idea: String): Team @auth
+ leave_team: User @auth
+ }
+
+ type Team {
+ id: ID!
+ name: String!
+ picture: String
+ members: [User!]
+ interests: [String!]
+ description: String
+ project_idea: String
+ notifications: [Notification!]!
+ public: Boolean
+ }
+`
\ No newline at end of file
diff --git a/server/src/typeDefs/user.ts b/server/src/typeDefs/user.ts
new file mode 100644
index 00000000..3ac27ad3
--- /dev/null
+++ b/server/src/typeDefs/user.ts
@@ -0,0 +1,30 @@
+const { gql } = require("apollo-server-express");
+
+export default gql`
+ extend type Query {
+ users(search: String, skill: String, name: String, email: String, grad_year: String, school: String, visible: Int): [User!]! @auth
+ user(user_id: String): User! @auth
+ user_profile: User! @auth
+ }
+
+ extend type Mutation {
+ update_user(name: String email: String, grad_year: String, school: String, contact: String, skills: [String], experience: String, contact_method: String, visible: Int): User! @auth
+ }
+
+ type User {
+ id: ID!
+ uuid: String
+ name: String!
+ email: String!
+ school: String
+ grad_year: String
+ beginner: Boolean
+ skills: [String!]
+ experience: String
+ contact: String
+ contact_method: String
+ visible: Int
+ team: Team
+ slackid: String
+ }
+`
\ No newline at end of file
diff --git a/server/src/types/index.ts b/server/src/types/index.ts
new file mode 100644
index 00000000..95fdde9d
--- /dev/null
+++ b/server/src/types/index.ts
@@ -0,0 +1,7 @@
+export * from './notification'
+
+export * from './mongoose'
+
+export * from './team'
+
+export * from './user'
\ No newline at end of file
diff --git a/server/src/types/mongoose.ts b/server/src/types/mongoose.ts
new file mode 100644
index 00000000..ab1d4f97
--- /dev/null
+++ b/server/src/types/mongoose.ts
@@ -0,0 +1,9 @@
+import { Model, Document, Types } from 'mongoose'
+
+type Omit = Pick>;
+export interface RootDocument {
+ _id: Types.ObjectId;
+}
+export function createNew(model: Model, doc: Omit) {
+ return new model(doc);
+}
\ No newline at end of file
diff --git a/server/src/types/notification.ts b/server/src/types/notification.ts
new file mode 100644
index 00000000..c50351bb
--- /dev/null
+++ b/server/src/types/notification.ts
@@ -0,0 +1,20 @@
+import { RootDocument } from './mongoose'
+import { Document } from 'mongoose'
+import { IUser } from './user'
+import { ITeam } from './team'
+
+export interface INotification extends RootDocument {
+ message: string;
+ bio: string;
+ idea: string;
+ notificationType: string;
+ sender: IUser & ITeam;
+ senderType: string;
+ receiverType: string;
+ receiver: IUser & ITeam;
+ resolved: boolean;
+
+}
+
+export type INotificationMongoose = (INotification & Document);
+
diff --git a/server/src/types/team.ts b/server/src/types/team.ts
new file mode 100644
index 00000000..f1300daf
--- /dev/null
+++ b/server/src/types/team.ts
@@ -0,0 +1,17 @@
+import { RootDocument } from './mongoose'
+import { Document } from 'mongoose'
+import { IUser } from './user'
+
+export interface ITeam extends RootDocument{
+ uuid: string;
+ creator: string;
+ name: string;
+ picture?: string;
+ members: IUser[];
+ interests?: string[];
+ description?: string;
+ project_idea?: string;
+ public: boolean;
+}
+
+export type ITeamMongoose = (ITeam & Document);
diff --git a/server/src/types/user.ts b/server/src/types/user.ts
new file mode 100644
index 00000000..6ad82f59
--- /dev/null
+++ b/server/src/types/user.ts
@@ -0,0 +1,25 @@
+import { RootDocument } from './mongoose'
+import { Document } from 'mongoose'
+import { ITeam } from './team'
+
+export interface IUser extends RootDocument {
+ uuid: string;
+ email: string;
+ name: string;
+ token: string | null;
+ admin?: boolean;
+ school?: string;
+ grad_year?: string;
+ skills?: string[];
+ beginner?: boolean;
+ experience?: string;
+ contact?: string;
+ image?: string;
+ contact_method?: string;
+ visible?: number;
+ team?: ITeam;
+ slackid: string;
+}
+
+export type IUserMongoose = (IUser & Document);
+
diff --git a/server/src/utils/index.ts b/server/src/utils/index.ts
new file mode 100644
index 00000000..915834d8
--- /dev/null
+++ b/server/src/utils/index.ts
@@ -0,0 +1 @@
+export { default as sendSlackMessage } from './slack'
\ No newline at end of file
diff --git a/server/src/sendSlackMessage.ts b/server/src/utils/slack.ts
similarity index 100%
rename from server/src/sendSlackMessage.ts
rename to server/src/utils/slack.ts
diff --git a/server/tsconfig.json b/server/tsconfig.json
index c8eb0cb7..8638fa0a 100644
--- a/server/tsconfig.json
+++ b/server/tsconfig.json
@@ -20,7 +20,8 @@
"noUnusedParameters": false,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
- "esModuleInterop": true
+ "esModuleInterop": true,
+ "skipLibCheck": true
},
"include": [
"src/**/*"
diff --git a/workspace.code-workspace b/workspace.code-workspace
new file mode 100644
index 00000000..362d7c25
--- /dev/null
+++ b/workspace.code-workspace
@@ -0,0 +1,7 @@
+{
+ "folders": [
+ {
+ "path": "."
+ }
+ ]
+}
\ No newline at end of file