Compare commits

...

7 Commits

9 changed files with 81 additions and 35 deletions

@ -1,13 +1,13 @@
import { AsyncData } from "#app"; import { AsyncData } from "#app";
const useApiFetch = async <T>(url: string, options?: any) => { const useApiFetch = async <T>(url: string, options?: any) => {
// const { token } = useAuth(); const { token } = useAuth();
let head = { let head = {
...(options?.headers || {}), ...(options?.headers || {}),
}; };
// if (token.value) { if (token.value) {
// head.Authorization = token.value; head.Authorization = token.value;
// } }
/* const cached = useSessionStorage<T>(url, null, { /* const cached = useSessionStorage<T>(url, null, {
serializer: StorageSerializers.object, serializer: StorageSerializers.object,
}); });

@ -6,9 +6,7 @@ const reducer = (pv, cv) => {
return { ...pv, [cv]: `plugins/${cv}/plugin.min.js` }; return { ...pv, [cv]: `plugins/${cv}/plugin.min.js` };
}; };
const external_plugins = plugins.reduce((pv, cv) => { const external_plugins = plugins.reduce(reducer);
return { ...pv, [cv]: `plugins/${cv}/plugin.min.js` };
}, {});
const base_url = "/tinymce"; const base_url = "/tinymce";
export const fancy = { export const fancy = {
branding: false, branding: false,
@ -94,7 +92,7 @@ export const comment = {
}, },
}, },
schema: "html5", schema: "html5",
external_plugins, external_plugins: ["link"].reduce(reducer),
toolbar: "bold italic underline | link", toolbar: "bold italic underline | link",
contextmenu: "bold italic underline | paste | link", contextmenu: "bold italic underline | paste | link",
}; };
@ -140,7 +138,7 @@ export const bare = {
}, },
}, },
schema: "html5", schema: "html5",
external_plugins, external_plugins: ["link"].reduce(reducer),
toolbar: "bold italic underline | hr link", toolbar: "bold italic underline | hr link",
contextmenu: "bold italic underline | paste | hr link", contextmenu: "bold italic underline | paste | hr link",
}; };

@ -1,4 +1,4 @@
import mongoose, { PopulatedDoc, Document, Model } from "mongoose"; import mongoose, { Document, Model, PopulatedDoc } from "mongoose";
import SequenceFactory from "mongoose-sequence"; import SequenceFactory from "mongoose-sequence";
import bcrypt from "bcryptjs"; import bcrypt from "bcryptjs";
import md5 from "blueimp-md5"; import md5 from "blueimp-md5";
@ -7,7 +7,7 @@ import { hasMigrated } from "@dbconfig";
import { IBand } from "./band"; import { IBand } from "./band";
import { IStory } from "./stories/index"; import { IStory } from "./stories/index";
import { QuickMenuItem, QuickMenuSchema } from "./quickMenu"; import { QuickMenuItem, QuickMenuSchema } from "./quickMenu";
import { FilterPick, PopulatedDocKeys, PopulatedPick } from "~/utils/filter"; // import { FilterPick, PopulatedDocKeys, PopulatedPick } from "~/utils/filter";
const AutoIncrement = SequenceFactory(mongoose); const AutoIncrement = SequenceFactory(mongoose);
interface IIPLogEntry { interface IIPLogEntry {
@ -70,7 +70,8 @@ export interface IUser extends Document {
quickMenuConfig: QuickMenuItem[]; quickMenuConfig: QuickMenuItem[];
notifyOnReviewReply?: boolean; notifyOnReviewReply?: boolean;
validPassword(password: string): boolean; validPassword(password: string): boolean;
generateJWT(jwtSecret: string): string; generateRefreshToken(jwtSecret: string): string;
generateAccessToken(jwtSecret: string): string;
} }
// type iut = IUser; // type iut = IUser;
interface UModel extends Model<IUser> { interface UModel extends Model<IUser> {
@ -272,11 +273,16 @@ UserSchema.methods.validPassword = function (password: string): boolean {
return md5(password) === this.password || bcrypt.compareSync(password, this.password) || false; return md5(password) === this.password || bcrypt.compareSync(password, this.password) || false;
}; };
UserSchema.methods.generateJWT = function (jwtKey: string): string { UserSchema.methods.generateRefreshToken = function (jwtKey: string): string {
let token = jwt.sign({ id: this._id, isAdmin: this.profile.isAdmin }, jwtKey, { return jwt.sign({ id: this._id, isAdmin: this.profile.isAdmin }, jwtKey, {
expiresIn: "14 days", expiresIn: "14 days",
}); });
return token; };
UserSchema.methods.generateAccessToken = function (jwtKey: string): string {
return jwt.sign({ id: this._id, isAdmin: this.profile.isAdmin }, jwtKey, {
expiresIn: "15m",
});
}; };
hasMigrated && !mongoose.models.User && UserSchema.plugin(AutoIncrement, { id: "userid", inc_field: "_id" }); hasMigrated && !mongoose.models.User && UserSchema.plugin(AutoIncrement, { id: "userid", inc_field: "_id" });

@ -65,16 +65,18 @@ export default defineNuxtConfig({
auth: { auth: {
baseURL: "/api/auth", baseURL: "/api/auth",
provider: { provider: {
type: "local", type: "refresh",
pages: { pages: {
login: "/auth/login", login: "/auth/login",
}, },
token: { token: {
signInResponseTokenPointer: "/token", signInResponseTokenPointer: "/token/access",
type: "Bearer", type: "Bearer",
headerName: "Authorization", headerName: "Authorization",
maxAgeInSeconds: 14 * 24 * 60 * 60, maxAgeInSeconds: 14 * 24 * 60 * 60,
// sameSiteAttribute: , },
refreshToken: {
signInResponseRefreshTokenPointer: "/token/refresh",
}, },
// @ts-ignore // @ts-ignore
sessionDataType: {} as IUser, sessionDataType: {} as IUser,
@ -85,6 +87,10 @@ export default defineNuxtConfig({
path: "/session", path: "/session",
method: "get", method: "get",
}, },
refresh: {
path: "/refresh",
method: "post",
},
}, },
}, },
globalAppMiddleware: false, globalAppMiddleware: false,

@ -22,8 +22,7 @@
"dependencies": { "dependencies": {
"@ant-design-vue/nuxt": "^1.4.1", "@ant-design-vue/nuxt": "^1.4.1",
"@pinia/nuxt": "^0.4.11", "@pinia/nuxt": "^0.4.11",
"@sidebase/nuxt-auth": "0.6.0-beta.6", "@sidebase/nuxt-auth": "0.7.0",
"@tinymce/tinymce-vue": "^5.1.1",
"@types/jsonwebtoken": "^9.0.3", "@types/jsonwebtoken": "^9.0.3",
"@types/lodash-es": "^4.17.12", "@types/lodash-es": "^4.17.12",
"@types/turndown": "^5.0.4", "@types/turndown": "^5.0.4",

@ -28,11 +28,14 @@ export default eventHandler(async (event) => {
message: 'Account inactive!<br><a href="/activate/resend">Resend verification</a>?', message: 'Account inactive!<br><a href="/activate/resend">Resend verification</a>?',
}); });
} }
let tok = user.generateJWT(useRuntimeConfig().jwt); let tok = user.generateRefreshToken(useRuntimeConfig().jwt);
// setCookie(event, "rockfic_cookie", tok); // setCookie(event, "rockfic_cookie", tok);
return { return {
user, user,
token: tok, token: {
refresh: tok,
access: user.generateAccessToken(useRuntimeConfig().jwt),
},
}; };
} else { } else {
throw createError({ statusCode: 401, message: wrongMsg }); throw createError({ statusCode: 401, message: wrongMsg });

@ -0,0 +1,27 @@
import jswt from "jsonwebtoken";
import { IJwt } from "@server/types/authstuff";
import { User } from "@models/user";
import { log } from "@server/logger";
const { verify } = jswt;
export default eventHandler(async (ev) => {
const body = await readBody<any>(ev);
const errMsg = createError({ statusCode: 403, message: "could not verify!" });
const { jwt } = useRuntimeConfig();
log.debug(JSON.stringify(body), { label: "WHAT???" });
if (!body.refreshToken) {
throw errMsg;
}
const decoded = verify(body.refreshToken, jwt) as IJwt | undefined;
if (!decoded) {
throw errMsg;
}
const user = await User.findById(decoded.id);
if (!user) throw errMsg;
return {
token: {
access: user.generateAccessToken(jwt),
refresh: user.generateRefreshToken(jwt),
},
};
});

@ -1,6 +1,6 @@
export default eventHandler((event) => { export default eventHandler((event) => {
let ahead = (getHeaders(event).authorization || getCookie(event, "auth:token") || "")?.replace("Bearer ", ""); let ahead = (getHeaders(event).authorization || "")?.replace("Bearer ", "");
if (event.context.currentUser) { if (event.context.currentUser && ahead) {
return { return {
token: ahead, token: ahead,
user: event.context.currentUser, user: event.context.currentUser,

@ -2,19 +2,26 @@ import jwt from "jsonwebtoken";
import { log } from "@server/logger"; import { log } from "@server/logger";
import { messages } from "@server/constants"; import { messages } from "@server/constants";
import { User } from "@models/user"; import { User } from "@models/user";
import { AccessToken } from "@models/oauth";
import { IJwt } from "@server/types/authstuff";
export default defineEventHandler(async (event) => { export default defineEventHandler(async (event) => {
let ahead = (getHeaders(event).authorization || getCookie(event, "auth:token") || "")?.replace("Bearer ", ""); let ahead = (getHeaders(event).authorization || "")?.replace("Bearer ", "");
// console.log("in here fucknuts", ahead);
// log.debug(`'${ahead}'`, { label: "idk" });
if (ahead) { if (ahead) {
let toktok = jwt.verify( let toktok: jwt.JwtPayload;
ahead, try {
// ahead.replace("Bearer ", ""), toktok = jwt.verify(ahead, useRuntimeConfig().jwt) as IJwt;
useRuntimeConfig().jwt,
) as jwt.JwtPayload;
let user = await User.findById(toktok.id as number).exec(); let user = await User.findById(toktok.id as number).exec();
if (user && toktok) event.context.currentUser = user; if (user && toktok) event.context.currentUser = user;
// setCookie(event, "auth:token", ahead) } catch (e) {
const t = await AccessToken.findOne({ token: ahead });
if (!t)
throw createError({
statusCode: 401,
message: messages[401],
});
let user = await User.findById(t.userID);
if (user) event.context.currentUser = user;
}
} }
}); });