auth mw stuff
This commit is contained in:
1 parent
d868baade5
commit
a79c11496b
8 files changed
+166
-31
No files matched your search
@@ -3,11 +3,9 @@ import { getCookies, setCookie } from "$std/http/cookie.ts"
|
||||
import { createPg } from "api/pg.ts"
|
||||
|
||||
// Define public paths that don't require authentication
|
||||
const PUBLIC_PATHS = [
|
||||
"/",
|
||||
"/api/auth/login",
|
||||
"/api/auth/register",
|
||||
"/api/auth/logout",
|
||||
const PROTECTED = [
|
||||
"/home",
|
||||
"/api/auth",
|
||||
]
|
||||
|
||||
// Sessions storage shared between routes
|
||||
@@ -18,11 +16,8 @@ export async function authMiddleware(req: Request, ctx: FreshContext): Promise<R
|
||||
const url = new URL(req.url)
|
||||
const path = url.pathname
|
||||
|
||||
console.log("authing...")
|
||||
|
||||
// Allow public paths without authentication
|
||||
if (PUBLIC_PATHS.includes(path)) {
|
||||
console.log("noauth")
|
||||
if (!PROTECTED.includes(path)) {
|
||||
return await ctx.next()
|
||||
}
|
||||
|
||||
@@ -66,7 +61,6 @@ export async function authMiddleware(req: Request, ctx: FreshContext): Promise<R
|
||||
ctx.state.user = user
|
||||
ctx.state.pg = pg
|
||||
|
||||
console.log("woas")
|
||||
|
||||
return await ctx.next()
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
import type Log from 'bunyan';
|
||||
import type { PrismaClient, Want, User, Listing, Offer, } from '@prisma/client';
|
||||
import assert from 'assert/strict';
|
||||
import groupBy from 'lodash/groupBy';
|
||||
import sortBy from 'lodash/sortBy';
|
||||
import flatMap from 'lodash/flatMap';
|
||||
import { Context } from 'koa';
|
||||
|
||||
import { logAxiosError, wantDetails } from './utils';
|
||||
import { Pg } from './pg';
|
||||
|
||||
export enum Status {
|
||||
Complete = 'Complete',
|
||||
Confirmed = 'Confirmed',
|
||||
Accepted = 'Accepted',
|
||||
Pending = 'Pending',
|
||||
Declined = 'Declined',
|
||||
}
|
||||
|
||||
function sortOffers(o) {
|
||||
return Object.values(Status).indexOf(o.status);
|
||||
}
|
||||
|
||||
export default function createOffers(log: Log, pg: Pg) {
|
||||
async function generate() {
|
||||
const listings = flatMap(await pg.interestingListings());
|
||||
log.debug('generateOffers', { listings: listings.length });
|
||||
|
||||
const shipping = 7.5; // yolt
|
||||
|
||||
const offers = listings.map(l => ({
|
||||
userId: l.want.user.id,
|
||||
listingId: l.id,
|
||||
wantId: l.want.id,
|
||||
|
||||
status: Status.Pending,
|
||||
|
||||
condition: l.data.condition,
|
||||
|
||||
item: l.data.price.value,
|
||||
shipping,
|
||||
total: l.data.price.value + shipping,
|
||||
}))
|
||||
|
||||
// we must sort the offers by price,
|
||||
// sometimes a seller has multiples of a want
|
||||
// to deal with this we just ignore duplicates on insert
|
||||
// and ensure the cheapest one goes in first
|
||||
const sorted = sortBy(offers, ['item']);
|
||||
|
||||
// TODO probably need to take one of each condition of record from a store
|
||||
// eg. they have a VG+ and a M we should make offers for each
|
||||
|
||||
log.trace('generated offers', sorted);
|
||||
const inserts = await pg.offersUpdate(sorted);
|
||||
|
||||
return inserts;
|
||||
}
|
||||
|
||||
async function accept(ctx: Context) {
|
||||
const { id } = ctx.request.body;
|
||||
ctx.assert(id, 401, 'no id supplied');
|
||||
|
||||
// check the user actually has this offer
|
||||
const offer = await pg.userOfferFind(ctx.state.user, id);
|
||||
return pg.offerStatusSet([offer.id], Status.Accepted);
|
||||
}
|
||||
|
||||
async function statusSet(user: User, ids: UUID[], status: Status) {
|
||||
log.info({ status, ids }, 'setting offer status');
|
||||
|
||||
// const offer = await pg.offerFindId(ids);
|
||||
const update = await pg.offerStatusSet(ids, status);
|
||||
|
||||
// forget about this for now
|
||||
// if (status === Status.Complete) {
|
||||
// log.info({ id, status }, 'completed offer, removing want...');
|
||||
// await pg.wantRm(offer.wantId);
|
||||
// }
|
||||
|
||||
return update;
|
||||
}
|
||||
|
||||
// converts offers into groups based on seller
|
||||
// includes some bits of info about shipping etc
|
||||
async function acpOffers() {
|
||||
const offers = await pg.offersAdmin();
|
||||
|
||||
const grouped = groupBy(offers, o => o.listing.data.seller.id);
|
||||
|
||||
const sellerOffers = sortBy(Object.values(grouped).map(offers => {
|
||||
const shipping = offers[0]?.listing.data.seller.shipping;
|
||||
const bundle = {
|
||||
username: offers[0]?.listing.data.seller.username,
|
||||
seller: offers[0]?.listing.data.seller.id,
|
||||
shipsFrom: offers[0]?.listing.data.ships_from,
|
||||
shipping,
|
||||
offers: sortBy(offers, sortOffers),
|
||||
mentionsAustralia: shipping.toLowerCase().includes('australia'),
|
||||
mentionsWorldwide: shipping.toLowerCase().includes('world'),
|
||||
}
|
||||
|
||||
return bundle;
|
||||
}), bundle => -bundle.offers.length);
|
||||
|
||||
return sellerOffers;
|
||||
}
|
||||
|
||||
// also groups offers by seller for users
|
||||
// but mostly just munges the structure so the details
|
||||
// are easily available
|
||||
async function userOffers(user: User) {
|
||||
const offers = await pg.userOffers(user);
|
||||
const groups = Object.values(groupBy(offers, (o) => o.wantId))
|
||||
.map(g => {
|
||||
// the offer status is just the most advanced status
|
||||
// based on sort
|
||||
const offers = sortBy(g, sortOffers);
|
||||
const status = offers[0].status;
|
||||
|
||||
// now actually sort them by price
|
||||
offers.sort((a, b) => a.total - b.total);
|
||||
|
||||
const details = offers[0].want.data;
|
||||
|
||||
return {
|
||||
details,
|
||||
offers,
|
||||
status,
|
||||
};
|
||||
});
|
||||
|
||||
return groups;
|
||||
}
|
||||
|
||||
async function samples() {
|
||||
const user = await pg.userFindEmail('ntr@mnml.gg');
|
||||
const offerGroups = await userOffers(user);
|
||||
const i = Math.floor(Math.random() * offerGroups.length / 2);
|
||||
return offerGroups[i];
|
||||
}
|
||||
|
||||
return {
|
||||
generate,
|
||||
accept,
|
||||
statusSet,
|
||||
acpOffers,
|
||||
userOffers,
|
||||
samples,
|
||||
};
|
||||
}
|
||||
|
||||
export type Offers = ReturnType<typeof createOffers>;
|
||||
@@ -32,6 +32,8 @@ function Main({ wants, offers }) {
|
||||
);
|
||||
}
|
||||
|
||||
console.log(offers)
|
||||
|
||||
return (
|
||||
<main>
|
||||
<nav>
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import { defineConfig } from "$fresh/server.ts";
|
||||
// import twind from "$fresh/plugins/twindv1.ts";
|
||||
// import twindConfig from "./twind.config.ts";
|
||||
import { authMiddleware } from "api/auth.middleware.ts";
|
||||
import { errorMiddleware } from "api/error.middleware.ts";
|
||||
import lessPlugin from "./less.plugin.ts";
|
||||
|
||||
export default defineConfig({
|
||||
@@ -10,8 +8,4 @@ export default defineConfig({
|
||||
// twind(twindConfig),
|
||||
lessPlugin()
|
||||
],
|
||||
middleware: {
|
||||
auth: authMiddleware,
|
||||
error: errorMiddleware,
|
||||
}
|
||||
});
|
||||
+2
-2
@@ -4,6 +4,7 @@
|
||||
|
||||
import * as $_404 from './routes/_404.tsx'
|
||||
import * as $_app from './routes/_app.tsx'
|
||||
import * as $_middleware from './routes/_middleware.ts'
|
||||
import * as $api_auth_login from './routes/api/auth/login.ts'
|
||||
import * as $api_auth_logout from './routes/api/auth/logout.ts'
|
||||
import * as $api_auth_register from './routes/api/auth/register.ts'
|
||||
@@ -11,7 +12,6 @@ import * as $api_auth_status from './routes/api/auth/status.ts'
|
||||
import * as $api_offers from './routes/api/offers.ts'
|
||||
import * as $api_wants from './routes/api/wants.ts'
|
||||
import * as $home from './routes/home.tsx'
|
||||
import * as $index from './routes/index.tsx'
|
||||
import * as $login from './routes/login.tsx'
|
||||
import * as $register from './routes/register.tsx'
|
||||
|
||||
@@ -21,6 +21,7 @@ const manifest = {
|
||||
routes: {
|
||||
'./routes/_404.tsx': $_404,
|
||||
'./routes/_app.tsx': $_app,
|
||||
'./routes/_middleware.ts': $_middleware,
|
||||
'./routes/api/auth/login.ts': $api_auth_login,
|
||||
'./routes/api/auth/logout.ts': $api_auth_logout,
|
||||
'./routes/api/auth/register.ts': $api_auth_register,
|
||||
@@ -28,7 +29,6 @@ const manifest = {
|
||||
'./routes/api/offers.ts': $api_offers,
|
||||
'./routes/api/wants.ts': $api_wants,
|
||||
'./routes/home.tsx': $home,
|
||||
'./routes/index.tsx': $index,
|
||||
'./routes/login.tsx': $login,
|
||||
'./routes/register.tsx': $register,
|
||||
},
|
||||
|
||||
@@ -1,18 +1,12 @@
|
||||
import { FreshContext } from "$fresh/server.ts";
|
||||
import { Pg } from 'api/pg.ts'
|
||||
import { User } from 'prisma/generated/index.d.ts'
|
||||
import { User } from 'prisma/generated/index.ts'
|
||||
import { authMiddleware } from 'api/auth.middleware.ts'
|
||||
import { errorMiddleware } from 'api/error.middleware.ts'
|
||||
|
||||
interface State {
|
||||
pg: Pg;
|
||||
user: User
|
||||
}
|
||||
|
||||
export async function handler(
|
||||
req: Request,
|
||||
ctx: FreshContext<State>,
|
||||
) {
|
||||
ctx.state.data = "myData";
|
||||
const resp = await ctx.next();
|
||||
resp.headers.set("server", "fresh server");
|
||||
return resp;
|
||||
}
|
||||
export const handler = [errorMiddleware, authMiddleware]
|
||||
@@ -1,10 +1,8 @@
|
||||
import { Handlers } from "$fresh/server.ts"
|
||||
import { createPg } from "../../api/pg.ts"
|
||||
|
||||
export const handler: Handlers = {
|
||||
async GET(_req, ctx) {
|
||||
const user = ctx.state.user
|
||||
const pg = createPg(console)
|
||||
const offers = await pg.userOffers(user)
|
||||
|
||||
return new Response(JSON.stringify(offers), {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Handlers, PageProps } from "$fresh/server.ts";
|
||||
import { createPg, Pg } from "../api/pg.ts";
|
||||
import Main from "../components/main.tsx";
|
||||
import { User } from 'prisma/generated/index.d.ts'
|
||||
import { User } from 'prisma/generated/index.ts'
|
||||
|
||||
export const handler: Handlers = {
|
||||
async GET(req, ctx) {
|
||||
|
||||
Reference in new issue
Block a user