dynamoose

Dynamoose: The Model object doesn't allow config as a parameter


I have created a model that was working when I had my backend functions running on my local machine, but when it uses AWS I get and authentication problem when the table is being queried:

2022-02-18T08:54:58.149Z    31785a81-ea8c-434b-832f-6dcff583c01c    ERROR   Unhandled Promise Rejection     
{
    "errorType": "Runtime.UnhandledPromiseRejection",
    "errorMessage": "AccessDeniedException: User: arn:aws:sts::xxxxxxxxx:assumed-role/dev-production-history-role/ppc-backend-functions-dev-queryProductionHistoryItems is not authorized to perform: dynamodb:CreateTable on resource: arn:aws:dynamodb:eu-west-1:xxxxxxxxxxxx:table/dev-production-history-table",
    "trace": [
        "Runtime.UnhandledPromiseRejection: AccessDeniedException: User: arn:aws:sts::xxxxxxxxx:assumed-role/dev-production-history-role/ppc-backend-functions-dev-queryProductionHistoryItems is not authorized to perform: dynamodb:CreateTable on resource: arn:aws:dynamodb:eu-west-1:xxxxxxxxx:table/dev-production-history-table",
        "    at process.<anonymous> (/var/runtime/index.js:35:15)",
        "    at process.emit (events.js:400:28)",
        "    at processPromiseRejections (internal/process/promises.js:245:33)",
        "    at processTicksAndRejections (internal/process/task_queues.js:96:32)"
    ]
}

This is how my model is defined:

const model = dynamoose.model<ProductionHistory>(DatabaseTableNames.productionHistoryTable, {schema});

From looking at possible solutions, it seems that adding {“create”: false} to the parameters might solve the issue, but in version 3 of Dynamoose you cannot add three parameters, so this will not work:

 const model = dynamoose.model<ProductionHistory>(DatabaseTableNames.productionHistoryTable,
    schema, {“create”: false});

Does anyone know how to overcome this problem so that it works with Dynamoose version 3?

I have made the changes that Charlie Fish suggested and I am now getting the following error:

2022-02-18T16:39:39.211Z    b00a36b8-c612-4886-b9fc-da7084527bf0    INFO    AccessDeniedException: User: arn:aws:sts::874124979428:assumed-role/dev-production-history-role/ppc-backend-functions-dev-queryProductionHistoryItems is not authorized to perform: dynamodb:Query on resource: arn:aws:dynamodb:eu-west-1:874124979428:table/dev-production-history-table
    at deserializeAws_json1_0QueryCommandError (/var/task/node_modules/dynamoose/node_modules/@aws-sdk/client-dynamodb/dist-cjs/protocols/Aws_json1_0.js:2984:41)
    at processTicksAndRejections (internal/process/task_queues.js:95:5)
    at async /var/task/node_modules/dynamoose/node_modules/@aws-sdk/middleware-serde/dist-cjs/deserializerMiddleware.js:7:24
    at async /var/task/node_modules/dynamoose/node_modules/@aws-sdk/middleware-signing/dist-cjs/middleware.js:11:20
    at async StandardRetryStrategy.retry (/var/task/node_modules/dynamoose/node_modules/@aws-sdk/middleware-retry/dist-cjs/StandardRetryStrategy.js:51:46)
    at async /var/task/node_modules/dynamoose/node_modules/@aws-sdk/middleware-logger/dist-cjs/loggerMiddleware.js:6:22
    at async main (/var/task/node_modules/dynamoose/dist/aws/ddb/internal.js:6:20)
    at async /var/task/node_modules/dynamoose/dist/ItemRetriever.js:105:32
    at async Object.queryByDate (/var/task/functions/production-history/query.js:1:1723)
    at async Runtime.l [as handler] (/var/task/functions/production-history/query.js:1:1974) {
  __type: 'com.amazon.coral.service#AccessDeniedException',
  '$fault': 'client',
  '$metadata': {
    httpStatusCode: 400,
    requestId: 'DCB6SNOH9O2NTRAS9LL3OJGEU7VV4KQNSO5AEMVJF66Q9ASUAAJG',
    extendedRequestId: undefined,
    cfId: undefined,
    attempts: 1,
    totalRetryDelay: 0
  },
  '$response': HttpResponse {
    statusCode: 400,
    headers: {
      server: 'Server',
      date: 'Fri, 18 Feb 2022 16:39:39 GMT',
      'content-type': 'application/x-amz-json-1.0',
      'content-length': '331',
      connection: 'keep-alive',
      'x-amzn-requestid': 'DCB6SNOH9O2NTRAS9LL3OJGEU7VV4KQNSO5AEMVJF66Q9ASUAAJG',
      'x-amz-crc32': '2950006190'
    },
    body: IncomingMessage {
      _readableState: [ReadableState],
      _events: [Object: null prototype],
      _eventsCount: 2,
      _maxListeners: undefined,
      socket: null,
      httpVersionMajor: 1,
      httpVersionMinor: 1,
      httpVersion: '1.1',
      complete: true,
      headers: [Object],
      rawHeaders: [Array],
      trailers: {},
      rawTrailers: [],
      aborted: false,
      upgrade: false,
      url: '',
      method: null,
      statusCode: 400,
      statusMessage: 'Bad Request',
      client: [TLSSocket],
      _consuming: false,
      _dumped: false,
      req: [ClientRequest],
      [Symbol(kCapture)]: false,
      [Symbol(RequestTimeout)]: undefined
    }
  }
}

This is my code now:

const model = dynamoose.model<ProductionHistory>(DatabaseTableNames.productionHistoryTable, schema);
const Table = new dynamoose.Table(DatabaseTableNames.productionHistoryTable, [model], {"create": false, "waitForActive": false});

Any ideas?


Solution

  • Disclaimer: this answer is based on Dynamoose v3.0.0 beta 1. Answers based on beta versions can become outdated quickly, so be sure to check for any updated details for your version of Dynamoose.


    In Dynamoose v3, a new class was introduced called Table. This represents a single DynamoDB Table. In previous versions of Dynamoose, a Model represented a single DynamoDB Table, but based on the API also kinda represented a specific entity or model in your data structure (ex. Movie, Order, User, etc). This lead to complications and confusion when it comes to single table design structures especially.

    In terms of code, what this means is the following.

    // If you have the following code in v2:
    
    const User = dynamoose.model("User", {"id": String});
    
    // It will be converted to this in v3:
    
    const User = dynamoose.model("User", {"id": String});
    const DBTable = new dynamoose.Table("DBTable", [User]);
    

    So basically you create a new Table instance based on your Model. In v3 if you try to use your Model without created a Table instance based on it, it will throw an error.

    Once you do that, the 3rd parameter of your Table constructor, you can pass in settings. Once of which being create. So you can set that to false as that parameter.

    Your code specifically would look something like:

    const model = dynamoose.model<ProductionHistory(DatabaseTableNames.productionHistoryTable, schema);
    const DBTable = new dynamoose.Table(DatabaseTableNames.productionHistoryTable, [model], {"create": false});