sourcefuse / loopback4-starter

Loopback 4 starter application. Multi-tenant architecture supported. Authentication, Authorization, Soft deletes, environment vars, Audit logs, included.
MIT License
158 stars 59 forks source link

Controller with relation returning 403 NotAllowed #21

Closed sherif2011 closed 5 years ago

sherif2011 commented 5 years ago

Hello @samarpan-b ,

So it's my first attempt to try creating a controller to post credentials for a specific user (with relations Belongsto/Hasmany). I am getting a 403, as if end-point isn't there. Please check full project here

below is a peak of controller:

import {post, param, requestBody} from '@loopback/rest'; import {UserRepository} from '../../repositories'; import {User, UserCredentials} from '../../models'; import {repository} from '@loopback/repository'; import {authorize} from 'loopback4-authorization';

export class UserCredentialsController { constructor( @repository(UserRepository) protected userRepository: UserRepository, ) {}

@authorize(['*']) @post('/users/{id}/credentials') async createAccount( @param.path.number('id') userId: typeof User.prototype.id, @requestBody() credentials: UserCredentials, ): Promise { return await this.userRepository.credentials(userId).create(credentials); } }

Thanks, Sherif

samarpanB commented 5 years ago

Can you please share your codebase ? Need to take a look.

sherif2011 commented 5 years ago

Sure, please check here: https://github.com/sherif2011/admin?files=1

sherif2011 commented 5 years ago

I have doubts about controller name? I already changed async function name to createCredential but that didn't help. Please check my codebase here: https://github.com/sherif2011/admin?files=1

mayank-SFIN571 commented 5 years ago

@sherif2011 Can you show me the request, that you are trying to make from front-end. I want to know what endpoint are you trying to hit.

mayank-SFIN571 commented 5 years ago

@sherif2011 you need to authenticate before you authorize in your controller.

Like you have done in this one

@authenticate(STRATEGY.BEARER)
  @authorize([
    PermissionKey.ViewAnyUser,
    PermissionKey.ViewOwnUser,
    PermissionKey.ViewTenantUser,
  ])
  @get('/users/count', {
    responses: {
      '200': {
        description: 'User model count',
        content: {'application/json': {schema: CountSchema}},
      },
    },
  })
  async count(
    @param.query.object('where', getWhereSchemaFor(User)) where?: Where<User>,
  ): Promise<Count> {
    return await this.userRepository.count(where);
  }
sherif2011 commented 5 years ago

@mayank-SFIN571 I am making a post request as below: http://localhost:3000/users/2/credentials (btw I already have user 2 created) with header: Content-Type: application/json;charset=UTF-8 Authorization: Bearer XXXXXXX Host: localhost:3000 Content-Length: 99

and body: { "deleted": false, "userId": 2, "authProvider": "internal", "password": "Test@1234" }

As for authentication, I am authorizing all *, the same way ping is authorized.

Thanks for looking into it.

mayank-SFIN571 commented 5 years ago

@sherif2011 I tried the same with your code, and it is working fine.

Sometimes build making process is inconsistent. Please delete the dist folder and make a fresh build.

sherif2011 commented 5 years ago

@mayank-SFIN571 I was able to overcome the 403 error, and it was related to the dist folder as you mentioned. Now I have a question and an issue:

Question: npm run build generates /dist10, while npm start uses /dist, so I had to delete dist and rename dist10 to dist, to overcome 403. Is there a way to get my builds directly generate js in /dist instead of dist10?

Issue: now that I was able to pass 403, I am getting a more meaningful error which is 422: {"error":{"statusCode":422,"name":"ValidationError","message":"The user_credentials instance is not valid. Details: user_id is not defined in the model (value: undefined).","details":{"context":"user_credentials","codes":{"user_id":["unknown-property"]},"messages":{"user_id":["is not defined in the model"]}}}}

My codebase is here Thanks!!

sherif2011 commented 5 years ago

@mayank-SFIN571 please disregard my question above, I was able to fix by adding --outDir in package.json:"build": "lb-tsc --outDir dist --copy-resources"

sherif2011 commented 5 years ago

Can you please help with this: now that I was able to pass 403, I am getting a more meaningful error which is 422: {"error":{"statusCode":422,"name":"ValidationError","message":"The user_credentials instance is not valid. Details: user_id is not defined in the model (value: undefined).","details":{"context":"user_credentials","codes":{"user_id":["unknown-property"]},"messages":{"user_id":["is not defined in the model"]}}}}

My codebase is here

Thanks!

sherif2011 commented 5 years ago

Any update please?

mayank-SFIN571 commented 5 years ago

@sherif2011 As i am pretty occupied today, I will be returning to you on this tomorrow first day in the morning.

sherif2011 commented 5 years ago

Ok thanks. I am basically trying to set user credentials but can't. Thanks!

Get Outlook for Androidhttps://aka.ms/ghei36


From: mayank-SFIN571 notifications@github.com Sent: Tuesday, July 23, 2019 6:39:22 AM To: sourcefuse/loopback4-starter loopback4-starter@noreply.github.com Cc: Sherif Mankarious smankarious@sunrisedataservices.com; Mention mention@noreply.github.com Subject: Re: [sourcefuse/loopback4-starter] Controller with relation returning 403 NotAllowed (#21)

@sherif2011https://github.com/sherif2011 As i am pretty occupied today, I will be returning to you on this tomorrow first day in the morning.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/sourcefuse/loopback4-starter/issues/21?email_source=notifications&email_token=AB4CJPOKM3VBSMDSIVGODODQA3UWVA5CNFSM4IFMCJJ2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD2S2V5Q#issuecomment-514173686, or mute the threadhttps://github.com/notifications/unsubscribe-auth/AB4CJPMYJSBKM72APJEPS43QA3UWVANCNFSM4IFMCJJQ.

sherif2011 commented 5 years ago

Any update?

samarpan-b commented 5 years ago

Yes. @mayank-SFIN571 have found the issue. He will be updating you in 30 mins. But meanwhile, just to let you know, in the starter codebase, we are actually creating user credentials as part of user creation. So, you may not need separate controller for credentials. Having separate controller for credentials will actually expose this model via GET APIs which we wanted to avoid as for security purposes.

Refer this method in user repository - https://github.com/sourcefuse/loopback4-starter/blob/5921b2ce610e7e58a55e42777db781e726534a89/src/repositories/user.repository.ts#L44

sherif2011 commented 5 years ago

Yes I saw those methods and wasnt sure how can I get my front end app call them? Can you please let me know? I really prefer using your methods. Should I just add end points to UserController? Can you provide an example please? Thanks!

mayank-SFIN571 commented 5 years ago

@sherif2011 You need to update your user.repository.ts file.

You have to change @hasOne(() => UserCredentials, {keyTo: 'user_id'}) credentials: UserCredentials;

to @hasOne(() => UserCredentials, {keyTo: 'userId'}) credentials: UserCredentials;

Here user_id was not valid as it was trying to find a property in user.model.ts but we have the property by the name userId.

This should solve the issue. If you still face the issue, please inform.

sherif2011 commented 5 years ago

Thanks @mayank-SFIN571 that was it!