diff --git a/packages/api/index.ts b/packages/api/index.ts index 1ed2a38..ba49ee7 100644 --- a/packages/api/index.ts +++ b/packages/api/index.ts @@ -3,8 +3,7 @@ import express, { Application, Request, Response } from "express"; import { NextFunction } from "express"; import SocketChannels from "@nirvana/core/sockets/channels"; import { UserService } from "./services/user.service"; -import { UserStatus } from "@nirvana/core/models"; -import { connectToDatabase } from "./services/database.service"; +import { UserStatus } from "@nirvana/core/models/user.model"; import cors from "cors"; import getConversationRoutes from "./routes/conversation"; import getSearchRoutes from "./routes/search"; @@ -29,7 +28,6 @@ app.use("/api/conversations", getConversationRoutes()); const PORT = 5000; var server = app.listen(PORT, () => console.log("express running")); -connectToDatabase(); // socket IO stuff @@ -106,22 +104,25 @@ io.on("connection", function (socket: any) { async (userGoogleId: string, newStatus: UserStatus) => { console.log("new status for user"); - const resultUpdate = await UserService.updateUserStatus( - userGoogleId, - newStatus - ); + // todo persist status changes + // const resultUpdate = await UserService.updateUserStatus( + // userGoogleId, + // newStatus + // ); // tell all rooms that the user is part of // that this user has updated their status - if (resultUpdate?.modifiedCount) { - socket.rooms.forEach((roomId: string) => { - io.in(roomId).emit( - SocketChannels.SEND_USER_STATUS_UPDATE, - userGoogleId, - newStatus - ); - }); - } + // if (resultUpdate?.modifiedCount) { + + // } + + socket.rooms.forEach((roomId: string) => { + io.in(roomId).emit( + SocketChannels.SEND_USER_STATUS_UPDATE, + userGoogleId, + newStatus + ); + }); } ); diff --git a/packages/api/package.json b/packages/api/package.json index 8599526..cdf5baa 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -12,6 +12,7 @@ "google-auth-library": "^7.14.0", "jsonwebtoken": "^8.5.1", "mongodb": "^4.4.1", + "mongoose": "^6.2.9", "socket.io": "^4.4.1" }, "scripts": { diff --git a/packages/api/routes/conversation.ts b/packages/api/routes/conversation.ts index 267615b..6cf5930 100644 --- a/packages/api/routes/conversation.ts +++ b/packages/api/routes/conversation.ts @@ -6,7 +6,6 @@ import { ObjectId } from "mongodb"; import Relationship from "@nirvana/core/models/relationship.model"; import { UserService } from "../services/user.service"; import { authCheck } from "../middleware/auth"; -import { collections } from "../services/database.service"; export default function getConversationRoutes() { const router = express.Router(); diff --git a/packages/api/routes/search.ts b/packages/api/routes/search.ts index 9238296..1a7dc62 100644 --- a/packages/api/routes/search.ts +++ b/packages/api/routes/search.ts @@ -1,7 +1,6 @@ import express, { Application, Request, Response } from "express"; import SearchResponse from "@nirvana/core/responses/search.response"; -import { User } from "@nirvana/core/models"; import { UserService } from "../services/user.service"; import { authCheck } from "../middleware/auth"; @@ -11,30 +10,30 @@ export default function getSearchRoutes() { router.use(express.json()); // get user details based on id token - router.get("/", authCheck, handleSearch); + // router.get("/", authCheck, handleSearch); return router; } -async function handleSearch(req: Request, res: Response) { - try { - const { query } = req.query; +// async function handleSearch(req: Request, res: Response) { +// try { +// const { query } = req.query; - if (!query) { - res.status(400).send("No search query provided!"); - return; - } +// if (!query) { +// res.status(400).send("No search query provided!"); +// return; +// } - // text search on users - const users: User[] | null = await UserService.getUsersLikeEmailAndName( - query as string - ); +// // text search on users +// const users: User[] | null = await UserService.getUsersLikeEmailAndName( +// query as string +// ); - const resObj = new SearchResponse(users ?? []); +// const resObj = new SearchResponse(users ?? []); - res.send(resObj); - } catch (error) { - console.log(error); - res.status(500).send(`something went wrong`); - } -} +// res.send(resObj); +// } catch (error) { +// console.log(error); +// res.status(500).send(`something went wrong`); +// } +// } diff --git a/packages/api/routes/user.ts b/packages/api/routes/user.ts index 02a3160..475e0aa 100644 --- a/packages/api/routes/user.ts +++ b/packages/api/routes/user.ts @@ -1,13 +1,13 @@ -import { GoogleUserInfo, User } from "@nirvana/core/models"; import express, { Application, Request, Response } from "express"; +import GoogleUserInfo from "@nirvana/core/models/googleUserInfo.model"; import { OAuth2Client } from "google-auth-library"; import { ObjectID } from "bson"; import { ObjectId } from "mongodb"; +import { User } from "@nirvana/core/models/user.model"; import { UserService } from "../services/user.service"; import { UserStatus } from "../../core/models/user.model"; import { authCheck } from "../middleware/auth"; -import { collections } from "../services/database.service"; const client = new OAuth2Client( "423533244953-banligobgbof8hg89i6cr1l7u0p7c2pk.apps.googleusercontent.com" @@ -83,8 +83,6 @@ async function login(req: Request, res: Response) { // create user if not exists const insertResult = await UserService.createUserIfNotExists(newUser); - newUser._id = insertResult?.insertedId; - // create jwt token with new user info insertResult diff --git a/packages/api/services/database.service.ts b/packages/api/services/database.service.ts index 8ea500c..9229db4 100644 --- a/packages/api/services/database.service.ts +++ b/packages/api/services/database.service.ts @@ -1,30 +1,42 @@ // External Dependencies import * as mongoDB from "mongodb"; -import { loadConfig } from "../config"; +import { IUser, UserStatus } from "@nirvana/core/models/user.model"; -// Global Variables -export const collections: { - users?: mongoDB.Collection; -} = {}; +import { ObjectId } from "mongodb"; +import { loadConfig } from "../config"; +import mongoose from "mongoose"; + +connectToDatabase().catch((err) => console.log(err)); // Initialize Connection export async function connectToDatabase() { const config = loadConfig(); - const client: mongoDB.MongoClient = new mongoDB.MongoClient( - config.MONGO_CONNECTION_STRING - ); + await mongoose.connect(config.MONGO_CONNECTION_STRING); - await client.connect(); - - const db: mongoDB.Db = client.db(process.env.DB_NAME); - - const usersCollection: mongoDB.Collection = db.collection("users"); - - collections.users = usersCollection; - - console.log( - `Successfully connected to database: ${db.databaseName} and collections` - ); + console.log(`Successfully connected to mongoose/mongodb`); } + +const userSchema = new mongoose.Schema( + { + name: { type: String, required: true }, + email: { type: String, required: true }, + googleId: { type: String, required: true }, // our Google id that every google user has unique that we are going to use for now + verifiedEmail: Boolean, + givenName: { type: String, required: true }, + familyName: { type: String, required: true }, + picture: String, + locale: String, + + // additional properties specific to our users collection + + createdDate: Date, + status: String, + lastUpdatedDate: Date, + _id: ObjectId, + }, + { collection: "users" } +); + +export const UserModel = mongoose.model("User", userSchema); diff --git a/packages/api/services/user.service.ts b/packages/api/services/user.service.ts index 9371569..e39f3dd 100644 --- a/packages/api/services/user.service.ts +++ b/packages/api/services/user.service.ts @@ -1,70 +1,56 @@ -import { GoogleUserInfo, User } from "@nirvana/core/models"; - +import GoogleUserInfo from "../../core/models/googleUserInfo.model"; import { ObjectId } from "mongodb"; +import { User } from "@nirvana/core/models/user.model"; +import { UserModel } from "./database.service"; import { UserStatus } from "../../core/models/user.model"; import axios from "axios"; -import { collections } from "./database.service"; export class UserService { - static async getUserByGoogleId(userId: string) { - const query = { googleId: userId }; - - const res = await collections.users?.findOne(query); - - // exists - if (res?._id) { - return res as User; - } - - return null; - } - static async getUserByEmail(email: string) { - const query = { email }; - - const res = await collections.users?.findOne(query); + const res = await UserModel.findOne({ email }); // exists - if (res?._id) { - return res as User; + if (!res?.$isEmpty) { + return res; } return null; } - static async getUsersLikeEmailAndName(searchQuery: string) { - // based on index defined in Mongo atlas - const query = { - $search: { - index: "default", - text: { - query: searchQuery, - path: { - wildcard: "*", - }, - }, - }, - }; + // static async getUsersLikeEmailAndName(searchQuery: string) { + // // based on index defined in Mongo atlas + // const query = { + // $search: { + // index: "default", + // text: { + // query: searchQuery, + // path: { + // wildcard: "*", + // }, + // }, + // }, + // }; - // const res = await collections.users?.find(query).toArray(); + // // const res = await collections.users?.find(query).toArray(); - const res = await collections.users?.aggregate([query]).toArray(); + // const res = await collections.users?.aggregate([query]).toArray(); - // exists - if (res?.length) { - return res as User[]; - } + // // exists + // if (res?.length) { + // return res as User[]; + // } - return null; - } + // return null; + // } static async createUserIfNotExists(newUser: User) { - const exists = ( - await collections.users?.findOne({ googleId: newUser.googleId }) - )?._id; + const getUser = await this.getUserByEmail(newUser.email); - if (!exists) { - return await collections.users?.insertOne(newUser); + if (!getUser) { + const newUser = new UserModel(User); + newUser.isNew = true; + + return newUser.save(); } // user with email exists already, don't create @@ -81,14 +67,14 @@ export class UserService { ).data; } - static async updateUserStatus(userGoogleId: string, newStatus: UserStatus) { - const query = { googleId: userGoogleId }; - const updateDoc = { - $set: { status: newStatus, lastUpdatedDate: new Date() }, - }; + // static async updateUserStatus(userId: string, newStatus: UserStatus) { + // const query = { googleId: userGoogleId }; + // const updateDoc = { + // $set: { status: newStatus, lastUpdatedDate: new Date() }, + // }; - const resultUpdate = await collections.users?.updateOne(query, updateDoc); + // const resultUpdate = UserModel.findByIdAndUpdate - return resultUpdate; - } + // return resultUpdate; + // } } diff --git a/packages/core/models/googleUserInfo.model.ts b/packages/core/models/googleUserInfo.model.ts index e39225d..0122dd6 100644 --- a/packages/core/models/googleUserInfo.model.ts +++ b/packages/core/models/googleUserInfo.model.ts @@ -1,6 +1,6 @@ import { ObjectId } from "mongodb"; -export class GoogleUserInfo { +export default class GoogleUserInfo { constructor( public id: string, public email: string, diff --git a/packages/core/models/index.ts b/packages/core/models/index.ts deleted file mode 100644 index 9676b82..0000000 --- a/packages/core/models/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./googleUserInfo.model"; -export * from "./user.model"; diff --git a/packages/core/models/user.model.ts b/packages/core/models/user.model.ts index 6556b40..e49a150 100644 --- a/packages/core/models/user.model.ts +++ b/packages/core/models/user.model.ts @@ -1,6 +1,24 @@ import { ObjectId } from "mongodb"; -export class User { +export interface IUser { + googleId: string; // our Google id that every google user has unique that we are going to use for now + email: string; + verifiedEmail: boolean; + name: string; + givenName: string; + familyName: string; + picture: string; + locale: string; + + // additional properties specific to our users collection + + createdDate: Date; + status: UserStatus; + lastUpdatedDate?: Date; + _id?: ObjectId; +} + +export class User implements IUser { constructor( public googleId: string, // our Google id that every google user has unique that we are going to use for now public email: string, diff --git a/packages/desktop/src/controller/nirvanaApi.ts b/packages/desktop/src/controller/nirvanaApi.ts index 5166008..4ea48b7 100644 --- a/packages/desktop/src/controller/nirvanaApi.ts +++ b/packages/desktop/src/controller/nirvanaApi.ts @@ -1,7 +1,7 @@ import axios, { AxiosRequestConfig, AxiosResponse, Method } from "axios"; import LoginResponse from "../../../core/responses/login.response"; -import { User } from "@nirvana/core/models"; +import { User } from "@nirvana/core/models/user.model"; // export const localHost = process.env.REACT_APP_API_DOMAIN; diff --git a/yarn.lock b/yarn.lock index 1d32b91..0886dbf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2032,6 +2032,13 @@ browserslist@^4.20.2: node-releases "^2.0.2" picocolors "^1.0.0" +bson@^4.2.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/bson/-/bson-4.6.2.tgz#3241c79d23d225b86ab6d2bc268b803d8a5fd444" + integrity sha512-VeJKHShcu1b/ugl0QiujlVuBepab714X9nNyBdA1kfekuDGecxgpTA2Z6nYbagrWFeiIyzSWIOzju3lhj+RNyQ== + dependencies: + buffer "^5.6.0" + bson@^4.6.1: version "4.6.1" resolved "https://registry.yarnpkg.com/bson/-/bson-4.6.1.tgz#2b5da517539bb0f7f3ffb54ac70a384ca899641c" @@ -2721,6 +2728,13 @@ debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2: dependencies: ms "2.1.2" +debug@4.x, debug@~4.3.1, debug@~4.3.2: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + debug@^3.1.0, debug@^3.1.1, debug@^3.2.7: version "3.2.7" resolved "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz" @@ -2728,13 +2742,6 @@ debug@^3.1.0, debug@^3.1.1, debug@^3.2.7: dependencies: ms "^2.1.1" -debug@~4.3.1, debug@~4.3.2: - version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== - dependencies: - ms "2.1.2" - decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" @@ -5300,6 +5307,11 @@ jws@^4.0.0: jwa "^2.0.0" safe-buffer "^5.0.1" +kareem@2.3.5: + version "2.3.5" + resolved "https://registry.yarnpkg.com/kareem/-/kareem-2.3.5.tgz#111fe9dbab754c8ed88b7a2360e2680cec1420ca" + integrity sha512-qxCyQtp3ioawkiRNQr/v8xw9KIviMSSNmy+63Wubj7KmMn3g7noRXIZB4vPCAP+ETi2SR8eH6CvmlKZuGpoHOg== + keyv@^3.0.0: version "3.1.0" resolved "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz" @@ -5809,7 +5821,7 @@ moment@^2.24.0, moment@^2.25.3, moment@^2.29.1: resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3" integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ== -mongodb-connection-string-url@^2.5.2: +mongodb-connection-string-url@^2.4.1, mongodb-connection-string-url@^2.5.2: version "2.5.2" resolved "https://registry.yarnpkg.com/mongodb-connection-string-url/-/mongodb-connection-string-url-2.5.2.tgz#f075c8d529e8d3916386018b8a396aed4f16e5ed" integrity sha512-tWDyIG8cQlI5k3skB6ywaEA5F9f5OntrKKsT/Lteub2zgwSUlhqEN2inGgBTm8bpYJf8QYBdA/5naz65XDpczA== @@ -5817,6 +5829,18 @@ mongodb-connection-string-url@^2.5.2: "@types/whatwg-url" "^8.2.1" whatwg-url "^11.0.0" +mongodb@4.3.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-4.3.1.tgz#e346f76e421ec6f47ddea5c8f5140e6181aaeb94" + integrity sha512-sNa8APSIk+r4x31ZwctKjuPSaeKuvUeNb/fu/3B6dRM02HpEgig7hTHM8A/PJQTlxuC/KFWlDlQjhsk/S43tBg== + dependencies: + bson "^4.6.1" + denque "^2.0.1" + mongodb-connection-string-url "^2.4.1" + socks "^2.6.1" + optionalDependencies: + saslprep "^1.0.3" + mongodb@^4.4.1: version "4.4.1" resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-4.4.1.tgz#e604cfbe2d5e125ae156ad04b52d261bed480b99" @@ -5829,6 +5853,31 @@ mongodb@^4.4.1: optionalDependencies: saslprep "^1.0.3" +mongoose@^6.2.9: + version "6.2.9" + resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-6.2.9.tgz#6318dceeebdd23d30a5a414a98bdfeab13fc83ef" + integrity sha512-6ApgF3rKYah5pUEO/1H+QrT0GT05OR7FprtVM45yzcrT/IKKlXizPyttrMiK1mLPt+55pGU7PMsBWY7yx/xZ4g== + dependencies: + bson "^4.2.2" + kareem "2.3.5" + mongodb "4.3.1" + mpath "0.8.4" + mquery "4.0.2" + ms "2.1.3" + sift "16.0.0" + +mpath@0.8.4: + version "0.8.4" + resolved "https://registry.yarnpkg.com/mpath/-/mpath-0.8.4.tgz#6b566d9581621d9e931dd3b142ed3618e7599313" + integrity sha512-DTxNZomBcTWlrMW76jy1wvV37X/cNNxPW1y2Jzd4DZkAaC5ZGsm8bfGfNOthcDuRJujXLqiuS6o3Tpy0JEoh7g== + +mquery@4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/mquery/-/mquery-4.0.2.tgz#a13add5ecd7c2e5a67e0f814b3c7acdfb6772804" + integrity sha512-oAVF0Nil1mT3rxty6Zln4YiD6x6QsUWYz927jZzjMxOK2aqmhEz5JQ7xmrKK7xRFA2dwV+YaOpKU/S+vfNqKxA== + dependencies: + debug "4.x" + ms@2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" @@ -7818,6 +7867,11 @@ side-channel@^1.0.4: get-intrinsic "^1.0.2" object-inspect "^1.9.0" +sift@16.0.0: + version "16.0.0" + resolved "https://registry.yarnpkg.com/sift/-/sift-16.0.0.tgz#447991577db61f1a8fab727a8a98a6db57a23eb8" + integrity sha512-ILTjdP2Mv9V1kIxWMXeMTIRbOBrqKc4JAXmFMnFq3fKeyQ2Qwa3Dw1ubcye3vR+Y6ofA0b9gNDr/y2t6eUeIzQ== + signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: version "3.0.7" resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz"