2

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 Answers3

0

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()
crbast
  • 2,192
  • 1
  • 11
  • 21
  • it does work in the sense that it store the data in the database, but it keeps returning the error afterwards – Rodrigo Alarcón Nov 03 '20 at 17:42
  • when does the error happen? (controller method) & can you please share your model file – crbast Nov 03 '20 at 19:02
  • I shared the file at the start of this question. Also, I found that the error occurs in the controller, in the line after the user is saved ```let accessToken = await auth.generate(user)``` I decided not to return the token after the user is saved and therefore, avoid the error, but I would prefer to return a token... – Rodrigo Alarcón Nov 04 '20 at 19:03
0

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).

Costin
  • 1
  • 1
  • 1
0

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)
...
Arash Younesi
  • 1,671
  • 1
  • 14
  • 23