Răsfoiți Sursa

hide account security props in api

Aneurin Barker Snook 1 an în urmă
părinte
comite
e9cf96b263
3 a modificat fișierele cu 34 adăugiri și 18 ștergeri
  1. 11 10
      src/account/api.ts
  2. 13 0
      src/account/http.ts
  3. 10 8
      web/src/api/account.ts

+ 11 - 10
src/account/api.ts

@@ -2,6 +2,7 @@ import type { AuthRequestHandler } from '../auth'
 import type { Context } from '../types'
 import type { RequestHandler } from 'express'
 import type { WithId } from 'mongodb'
+import { prepareAccount } from './http'
 import type { Account, AccountCreate, AccountUpdate } from './types'
 import { http, validate as v } from '@edge/misc-utils'
 
@@ -12,7 +13,7 @@ export function createAccount({ model }: Context): RequestHandler {
   }
 
   interface ResponseData {
-    account: WithId<Account>
+    account: WithId<Partial<Account>>
   }
 
   const readRequestData = v.validate<RequestData>({
@@ -29,7 +30,7 @@ export function createAccount({ model }: Context): RequestHandler {
       const account = await model.account.create(input.account)
       if (!account) return http.notFound(res, next, { reason: 'unexpectedly failed to get new account' })
 
-      const output: ResponseData = { account }
+      const output: ResponseData = { account: prepareAccount(account) }
       res.send(output)
       next()
     } catch (err) {
@@ -46,7 +47,7 @@ export function createAccount({ model }: Context): RequestHandler {
 /** Delete an account. */
 export function deleteAccount({ model }: Context): AuthRequestHandler {
   interface ResponseData {
-    account: WithId<Account>
+    account: WithId<Partial<Account>>
     herds: {
       deletedCount: number
     }
@@ -70,7 +71,7 @@ export function deleteAccount({ model }: Context): AuthRequestHandler {
 
       // Send output
       const output: ResponseData = {
-        account,
+        account: prepareAccount(account),
         herds: {
           deletedCount: deletedHerds,
         },
@@ -89,7 +90,7 @@ export function deleteAccount({ model }: Context): AuthRequestHandler {
 /** Get an account. */
 export function getAccount(): AuthRequestHandler {
   interface ResponseData {
-    account: WithId<Account>
+    account: WithId<Partial<Account>>
   }
 
   return async function (req, res, next) {
@@ -101,7 +102,7 @@ export function getAccount(): AuthRequestHandler {
 
     try {
       // Send output
-      const output: ResponseData = { account: req.account }
+      const output: ResponseData = { account: prepareAccount(req.account) }
       res.send(output)
       next()
     } catch (err) {
@@ -121,7 +122,7 @@ export function loginAccount({ auth, model }: Context): RequestHandler {
 
   interface ResponseData {
     token: string
-    account: WithId<Account>
+    account: WithId<Partial<Account>>
   }
 
   const readRequestData = v.validate<RequestData>({
@@ -148,7 +149,7 @@ export function loginAccount({ auth, model }: Context): RequestHandler {
       const token = await auth.sign(account._id)
 
       // Send output
-      const output: ResponseData = { token, account }
+      const output: ResponseData = { token, account: prepareAccount(account) }
       res.send(output)
       next()
     } catch (err) {
@@ -169,7 +170,7 @@ export function updateAccount({ model }: Context): AuthRequestHandler {
   }
 
   interface ResponseData {
-    account: WithId<Account>
+    account: WithId<Partial<Account>>
   }
 
   const readRequestData = v.validate<RequestData>({
@@ -198,7 +199,7 @@ export function updateAccount({ model }: Context): AuthRequestHandler {
       if (!account) return http.notFound(res, next)
 
       // Send output
-      const output: ResponseData = { account }
+      const output: ResponseData = { account: prepareAccount(account) }
       res.send(output)
       next()
     } catch (err) {

+ 13 - 0
src/account/http.ts

@@ -0,0 +1,13 @@
+import type { Account } from './types'
+import type { WithId } from 'mongodb'
+
+/**
+ * Prepare an account for display via API.
+ * This prevents sensitive fields being exposed.
+ */
+export function prepareAccount(account: WithId<Account>): WithId<Partial<Account>> {
+  return {
+    _id: account._id,
+    email: account.email,
+  }
+}

+ 10 - 8
web/src/api/account.ts

@@ -1,19 +1,17 @@
 import { request } from './lib'
-import type { Options, SomeRequired, WithId } from './lib'
+import type { Options, WithId } from './lib'
 
 /** Account data. */
 export interface Account {
   /** Email address. Used for authentication. */
   email: string
-  /** Password. Used for authentication. */
-  password: string
-  /** Password salt. Used for authentication. */
-  passwordSalt: string
 }
 
 /** Create account request data. */
 export interface CreateAccountRequest {
-  account: SomeRequired<Account, 'email' | 'password'>
+  account: Account & {
+    password: string
+  }
 }
 
 /** Create account response data. */
@@ -39,7 +37,9 @@ export interface GetAccountResponse {
 
 /** Account login request data. */
 export interface LoginAccountRequest {
-  account: Pick<Account, 'email' | 'password'>
+  account: Account & {
+    password: string
+  }
 }
 
 /** Account login response data. */
@@ -50,7 +50,9 @@ export interface LoginAccountResponse {
 
 /** Update account request data. */
 export interface UpdateAccountRequest {
-  account: Partial<Account>
+  account: Partial<Account> & {
+    password?: string
+  }
 }
 
 /** Update account response data. */