Adonis JS Primary key value is missing for user

Viewed 706

I'm trying to make a migratiion of users model from adonis to postgres but I keep getting this error Primary key value is missing for user

My model look like this:

class User extends Model {
  static boot () {
    super.boot()

    this.addHook('beforeSave', async (userInstance) => {
      if (userInstance.dirty.password) {
        userInstance.password = await Hash.make(userInstance.password)
      }
    })
  }

  tokens () {
    return this.hasMany('App/Models/Token')
  }
}

module.exports = User

And the migration I'm trying to run is:

/** @type {import('@adonisjs/lucid/src/Schema')} */
const Schema = use('Schema')

class UserSchema extends Schema {
  up () {
    this.create('users', (table) => {
      table.increments()
      table.string('username', 80).notNullable().unique()
      table.string('email', 254).notNullable().unique()
      table.string('password', 60).notNullable()
      table.timestamps()
    })
  }

  down () {
    this.drop('users')
  }
}

module.exports = UserSchema

I tried adding primary() to table.increments() asuming it is generating the auto increments id in postgre database. When I check the database the user is sometimes added, but with id's that goes from 2 to 4 and so on

The controller looks like this

const User = use('App/Models/User')

class UserController {
  async register({request, auth, response}) {
      const username = request.input("username")
      const email = request.input("email")
      const password = request.input("password")

      let user = new User()
      user.username = username
      user.email = email
      user.password = password

      user = await user.save()
      let accessToken = await auth.generate(user)
      return response.json({"user": user, "access_token": accessToken})
  }

  async login({request, auth, response}) {
    const email = request.input("email")
    const password = request.input("password");
    try {
      if (await auth.attempt(email, password)) {
        let user = await User.findBy('email', email)
        let accessToken = await auth.generate(user)
        return response.json({"user":user, "access_token": accessToken})
      }

    }
    catch (e) {
      return response.json({message: 'You first need to register!'})
    }
  }

    show ({ auth, params }) {
        if (auth.user.id !== Number(params.id)) {
          return "You cannot see someone else's profile"
        }
        return auth.user
    }
}

module.exports = UserController
3 Answers

table.increments() need column name as parameter -> table.increments(name)

Please read official knex documentation : https://knexjs.org/#Schema-increments

Example :

table.increments('id').primary()

The issue is with

user = await user.save()

that will return true when user is saved to db, passing that to auth.generate is what cause that error.

Just use something like

let success = await user.save()

and check success value after. Might want to return the token and 200 status only if user is saved (success is true).

The problem is that you overwrite user model instance in user = await user.save().

as @Costin say's simply storing result of await user.save() in new variable will solve the issue.

for example:

...
let saved = await user.save()
let accessToken = await auth.generate(user)
...
Related