Skip to content

Commit

Permalink
refactor: checkpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
Xunnamius committed Jun 1, 2022
1 parent eeb2858 commit 09b8388
Show file tree
Hide file tree
Showing 11 changed files with 1,843 additions and 430 deletions.
4 changes: 4 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ DISALLOWED_METHODS=
# bytes. Should be a string like 1kb, 1mb, 500b
MAX_CONTENT_LENGTH_BYTES=100kb

# Maximum number of parameters that can be passed to endpoints that accept
# multiple slash parameters.
MAX_PARAMS_PER_REQUEST=100

# Maximum allowed size of a tags array in a search query.
MAX_SEARCHABLE_TAGS=10

Expand Down
2 changes: 1 addition & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ module.exports = {
testEnvironment: 'node',
testRunner: 'jest-circus/runner',
// ? 1 hour so MMS and other tools don't choke during debugging
testTimeout: 5000,
testTimeout: 1000 * 60 * 60,
verbose: false,
testPathIgnorePatterns: ['/node_modules/'],
// ! If changed, also update these aliases in tsconfig.json,
Expand Down
4 changes: 2 additions & 2 deletions lib/mongo-item/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ export type ItemExistsOptions = {
*/
caseInsensitive?: boolean;
/**
* When looking for an item matching `{ _id: id }`, where the property is
* `"_id"` is a string, `id` will be optimistically wrapped in a `new
* When looking for an item matching `{ _id: id }`, where the descriptor key
* is the string `"_id"`, `id` will be optimistically wrapped in a `new
* ObjectId(id)` call. Set this to `false` to prevent this.
*
* @default true
Expand Down
14 changes: 7 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
"find-up": "^5.0.0",
"is-server-side": "^1.0.2",
"mongodb": "^4.6.0",
"named-app-errors": "^3.1.0",
"named-app-errors": "^3.2.0",
"next": "^12.1.6",
"node-fetch": "cjs",
"react": "^18.1.0",
Expand Down
37 changes: 36 additions & 1 deletion src/backend/db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export function getSchemaConfig(): DbSchema {
// ? https://stackoverflow.com/a/40914924/1367414
createOptions: { collation: { locale: 'en', strength: 2 } },
indices: [
{ spec: 'key' },
{
spec: 'username',
options: { unique: true }
Expand All @@ -46,6 +47,7 @@ export function getSchemaConfig(): DbSchema {
indices: [
{ spec: 'owner' },
{ spec: 'name-lowercase' },
{ spec: 'contents' },
// ? Wildcard indices to index permissions object keys
// ? https://www.mongodb.com/docs/manual/core/index-wildcard
{ spec: 'permissions.$**' }
Expand Down Expand Up @@ -223,7 +225,6 @@ export function toPublicNode(internalNode: InternalNode): PublicNode {
owner: internalNode.owner,
createdAt: internalNode.createdAt,
name: internalNode.name,
'name-lowercase': internalNode['name-lowercase'],
permissions: internalNode.permissions
} as {
[key in keyof PublicFileNode & keyof PublicMetaNode]:
Expand Down Expand Up @@ -261,3 +262,37 @@ export function toPublicUser(internalUser: InternalUser): PublicUser {
salt: internalUser.salt
};
}

export const publicUserProjection = {
_id: false,
user_id: { $toString: '$_id' },
username: true,
salt: true,
email: true
} as const;

export const publicFileNodeProjection = {
_id: false,
node_id: { $toString: '$_id' },
type: true,
owner: true,
createdAt: true,
modifiedAt: true,
name: true,
size: true,
text: true,
tags: true,
lock: true,
permissions: true
} as const;

export const publicMetaNodeProjection = {
_id: false,
node_id: { $toString: '$_id' },
type: true,
owner: true,
createdAt: true,
name: true,
contents: { $map: { input: '$contents', as: 'id', in: { $toString: '$$id' } } },
permissions: true
} as const;
2 changes: 2 additions & 0 deletions src/backend/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import type { Environment } from 'multiverse/next-env';
// eslint-disable-next-line @typescript-eslint/ban-types
export function getEnv<T extends Environment = Environment>() {
const env = getDefaultEnv({
MAX_PARAMS_PER_REQUEST: Number(process.env.MAX_PARAMS_PER_REQUEST) || 0,
MAX_SEARCHABLE_TAGS: Number(process.env.MAX_SEARCHABLE_TAGS) || 0,
MAX_NODE_NAME_LENGTH: Number(process.env.MAX_NODE_NAME_LENGTH) || 0,
MAX_USER_NAME_LENGTH: Number(process.env.MAX_USER_NAME_LENGTH) || 0,
Expand All @@ -31,6 +32,7 @@ export function getEnv<T extends Environment = Environment>() {

(
[
'MAX_PARAMS_PER_REQUEST',
'MAX_SEARCHABLE_TAGS',
'MAX_NODE_NAME_LENGTH',
'MAX_USER_NAME_LENGTH',
Expand Down
22 changes: 12 additions & 10 deletions src/backend/error.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
import { ErrorMessage as NamedErrorMessage } from 'named-app-errors';

/**
* A collection of possible error and warning messages.
*/
export const ErrorMessage = {
ItemNotFound: (itemName: string) => `${itemName} could not be found`,
ItemOrItemsNotFound: (itemsName: string) =>
`one or more ${itemsName} could not be found`,
...NamedErrorMessage,
TooManyItemsRequested: (itemsName: string) => `too many ${itemsName} requested`,
ForbiddenAction: () => 'you are not authorized to take this action',
DuplicateFieldValue: (prop: string) => `an item with that "${prop}" already exists`,
DuplicateSetMember: (prop: string) =>
`duplicate elements in \`${prop}\` are not allowed`,
InvalidField: (prop: string) =>
`the \`${prop}\` field is not allowed with this type of item`,
InvalidFieldValue: (prop: string) =>
`\`${prop}\` field has a missing, invalid, or illegal value`,
InvalidArrayValue: (prop: string) =>
`a \`${prop}\` array element has an invalid or illegal value`,
InvalidFieldValue: (prop: string, value?: string) =>
value
? `the \`${prop}\` field value "${value}" is invalid or illegal`
: `\`${prop}\` field has a missing, invalid, or illegal value`,
InvalidArrayValue: (prop: string, value?: string) =>
value
? `the \`${prop}\` array element "${value}" is invalid or illegal`
: `a \`${prop}\` array element has an invalid or illegal value`,
InvalidObjectKeyValue: (prop: string) =>
`a \`${prop}\` object key has an invalid or illegal value`,
IllegalUsername: () => 'a user with that username cannot be created',
Expand Down Expand Up @@ -49,5 +51,5 @@ export const ErrorMessage = {
InvalidRegexString: (prop: string) => `\`${prop}\`: invalid regex value`,
InvalidMatcher: (prop: string) => `invalid \`${prop}\`: must be an object`,
InvalidSpecifierCombination: () => `invalid combination of specifiers`,
InvalidObjectId: (id: string) => `invalid ${id}`
InvalidObjectId: (id: string) => `invalid id "${id}"`
};
Loading

0 comments on commit 09b8388

Please sign in to comment.