diff --git a/packages/models/index.js b/packages/models/index.js index db6b269..c3b835c 100644 --- a/packages/models/index.js +++ b/packages/models/index.js @@ -4,6 +4,7 @@ export { default as User } from './user.js' export { default as Quest } from './quest.js' export { default as Session } from './session.js' export { default as Command } from './command.js' +export { default as UserProfile } from './userProfile.js' export default async function connectDB(uri) { const db = await mongoose.connect(uri, { diff --git a/packages/models/user.js b/packages/models/user.js index 7bdb2f3..6c3bc44 100644 --- a/packages/models/user.js +++ b/packages/models/user.js @@ -1,24 +1,5 @@ import { model, Schema } from 'mongoose' -const progressSchema = new Schema({ - quest: { - type: String, - ref: 'Quest', - }, - sessions: [ - { - type: Schema.ObjectId, - ref: 'Session', - }, - ], - completionStatus: { - type: String, - enum: ['incomplete', 'completed'], - }, - startedAt: Date, - finishedAt: Date, -}) - const User = model( 'User', new Schema( @@ -42,7 +23,6 @@ const User = model( id: String, displayName: String, }, - progress: [progressSchema], }, { timestamps: true, diff --git a/packages/models/userProfile.js b/packages/models/userProfile.js new file mode 100644 index 0000000..61fe45d --- /dev/null +++ b/packages/models/userProfile.js @@ -0,0 +1,51 @@ +import { model, Schema } from 'mongoose' + +const progressSchema = new Schema({ + quest: { + type: String, + ref: 'Quest', + required: true, + }, + sessions: [ + { + type: Schema.ObjectId, + ref: 'Session', + required: true, + }, + ], + completed: { + type: Boolean, + default: false, + required: true, + }, + startedAt: { + type: Date, + required: true, + }, + finishedAt: Date, +}) + +const UserProfile = model( + 'UserProfile', + new Schema( + { + user: { + type: Schema.ObjectId, + ref: 'User', + unique: true, + required: true, + }, + progress: { + type: Map, + of: progressSchema, + default: {}, + required: true, + }, + }, + { + timestamps: true, + } + ) +) + +export default UserProfile diff --git a/server/src/auth/passport.js b/server/src/auth/passport.js index 9cd9011..47f9776 100644 --- a/server/src/auth/passport.js +++ b/server/src/auth/passport.js @@ -1,4 +1,5 @@ import passport from 'passport' +import { UserProfile } from '@linux-odyssey/models' import passwordStrategy from './passwordStrategy.js' import jwtStrategy from './jwtStrategy.js' import googleStrategy from './googleStrategy.js' @@ -24,7 +25,10 @@ if (enabledMethods.github) { } passport.serializeUser((user, done) => { - process.nextTick(() => { + process.nextTick(async () => { + if (!(await UserProfile.exists({ user: user._id }))) { + UserProfile.create({ user: user._id }) + } done(null, { _id: user._id, username: user.username, diff --git a/server/src/game/sessionManager.js b/server/src/game/sessionManager.js index 409f58e..6ab8c7c 100644 --- a/server/src/game/sessionManager.js +++ b/server/src/game/sessionManager.js @@ -1,4 +1,4 @@ -import { Session, Quest } from '@linux-odyssey/models' +import { Session, Quest, UserProfile } from '@linux-odyssey/models' import { createContainer, deleteContainer } from '../containers/docker.js' import SessionHandler from './sessionHandler.js' @@ -48,6 +48,23 @@ export async function createNewSession(user, questId) { const session = sessionHandler.getSession() await session.save() + + const userProfile = await UserProfile.findOne({ user: user._id }) + if (!userProfile) { + throw new Error(`UserProfile ${user._id} not found`) + } + + const progress = userProfile.progress.get(quest._id) + if (!progress) { + userProfile.progress.set(quest._id, { + quest: quest._id, + sessions: [session._id], + startedAt: new Date(), + }) + } else { + progress.sessions.push(session._id) + } + await userProfile.save() return session }