shireef khatab
shireef khatab

Reputation: 1005

Loopback error: Authorization Required

I have a loopback app with mongoDB as below:

when i login as Admin i cannot use post method on dishes. and i get authorization required error. that becomes possible only when i change the dishes role to ALLOW everyone.

how can i acheive the wanted result with keeping everyone on DENY and only ALLOW certain users to certain operations? thank you. here is my code..

app/server/model-config.json:

    {
  "_meta": {
    "sources": [
      "loopback/common/models",
      "loopback/server/models",
      "../common/models",
      "./models"
    ],
    "mixins": [
      "loopback/common/mixins",
      "loopback/server/mixins",
      "../node_modules/loopback-ds-timestamp-mixin",
      "../common/mixins",
      "./mixins"
    ]
  },
  "User": {
    "dataSource": "db"
  },
  "AccessToken": {
    "dataSource": "db",
    "public": false
  },
  "ACL": {
    "dataSource": "MongoDB",
    "public": false
  },
  "RoleMapping": {
    "dataSource": "MongoDB",
    "public": false
  },
  "Role": {
    "dataSource": "MongoDB",
    "public": false
  },
  "dishes": {
    "dataSource": "MongoDB",
    "public": true
  },
  "Customer": {
    "dataSource": "MongoDB",
    "public": true
  },
  "Comments": {
    "dataSource": "MongoDB",
    "public": true
  }
}

app/common/modles/dishes.json:

{
  "name": "dishes",
  "base": "PersistedModel",
  "idInjection": true,
  "options": {
    "validateUpsert": true
  },
  "properties": {
    "name": {
      "type": "string",
      "required": true
    },
    "description": {
      "type": "string",
      "required": true
    },
    "category": {
      "type": "string",
      "required": true
    },
    "image": {
      "type": "string",
      "required": true
    },
    "label": {
      "type": "string",
      "required": true,
      "default": "''"
    },
    "price": {
      "type": "string",
      "required": true,
      "default": "0"
    }
  },
  "mixins": {
    "TimeStamp": true
  },
  "validations": [],
  "relations": {
    "comments": {
      "type": "hasMany",
      "model": "Comments",
      "foreignKey": ""
    },
    "customers": {
      "type": "hasMany",
      "model": "Customer",
      "foreignKey": ""
    }
  },
  "acls": [
    {
      "accessType": "*",
      "principalType": "ROLE",
      "principalId": "$everyone",
      "permission": "DENY"
    },
    {
      "accessType": "READ",
      "principalType": "ROLE",
      "principalId": "$authenticated",
      "permission": "ALLOW"
    },
    {
      "accessType": "EXECUTE",
      "principalType": "ROLE",
      "principalId": "admin",
      "permission": "ALLOW",
      "property": "create"
    },
    {
      "accessType": "WRITE",
      "principalType": "ROLE",
      "principalId": "admin",
      "permission": "ALLOW"
    }
  ],
  "methods": {}
}

app/common/modles/comments.json:

    {
  "name": "Comments",
  "base": "PersistedModel",
  "idInjection": true,
  "options": {
    "validateUpsert": true
  },
  "properties": {
    "Rating": {
      "type": "number",
      "required": true,
      "default": 5
    },
    "comment": {
      "type": "string",
      "required": true
    }
  },
  "mixins": {
    "TimeStamp": true
  },
  "validations": [],
  "relations": {
    "dishes": {
      "type": "belongsTo",
      "model": "dishes",
      "foreignKey": ""
    },
    "customer": {
      "type": "belongsTo",
      "model": "Customer",
      "foreignKey": "customerId"
    }
  },
  "acls": [
    {
      "accessType": "*",
      "principalType": "ROLE",
      "principalId": "$everyone",
      "permission": "DENY"
    },
    {
      "accessType": "READ",
      "principalType": "ROLE",
      "principalId": "$authenticated",
      "permission": "ALLOW"
    },
    {
      "accessType": "EXECUTE",
      "principalType": "ROLE",
      "principalId": "$authenticated",
      "permission": "ALLOW",
      "property": "create"
    },
    {
      "accessType": "WRITE",
      "principalType": "ROLE",
      "principalId": "$owner",
      "permission": "ALLOW"
    }
  ],
  "methods": {}
}

app/common/modles/customer.json:

    {
  "name": "Customer",
  "base": "User",
  "idInjection": true,
  "options": {
    "validateUpsert": true
  },
  "properties": {},
  "validations": [],
  "relations": {
    "comments": {
      "type": "hasMany",
      "model": "Comments",
      "foreignKey": "customerId"
    }
  },
  "acls": [
    {
      "accessType": "*",
      "principalType": "ROLE",
      "principalId": "$everyone",
      "permission": "DENY"
    }
  ],
  "methods": {}
}

and app/server/boot/script.js:

    module.exports = function(app) {
var MongoDB = app.dataSources.MongoDB;

MongoDB.automigrate('Customer', function(err) {
   if (err) throw (err);
   var Customer = app.models.Customer;

   Customer.create([
    {username: 'Admin', email: '[email protected]', password: 'abcdef'},
    {username: 'muppala', email: '[email protected]', password: 'abcdef'}
  ], function(err, users) {
        if (err) throw (err);
        var Role = app.models.Role;
        var RoleMapping = app.models.RoleMapping;

        Role.find({ name: 'admin' }, function(err, results) {
            if (err) { throw err; }

            if (results.length < 1) {
                // now we know the DB doesn't have it already, so do the Role creation...
                //create the admin role
                Role.create({
                  name: 'admin'
                }, function(err, role) {
                  if (err) throw (err);
                   //make admin
                  role.principals.create({
                    principalType: RoleMapping.USER,
                    principalId: users[0].id
                  }, function(err, principal) {
                    if (err) throw (err);
                  });
                });
            }
        });
  });
});

};

Upvotes: 1

Views: 2542

Answers (2)

sonle
sonle

Reputation: 21

I am also having the same trouble as I come through the same assignment. Mr Kike's answer works for mine. First, from cmd, type

>mongo
>use conFusion   (Note: conFusion is the name of database of this assignment)
>show collections  (Note: to see all collections in database collections)
>db.Role.drop()    

And then run the loopback with node . again

Upvotes: 0

kike
kike

Reputation: 4463

Seeing your last question I imagine what happened.

Somehow the collection Role was created but not mapped to User.

I suggest you to change:

Role.find({ name: 'admin' }, function(err, results) {
            if (err) { throw err; }

            if (results.length < 1) {
                // now we know the DB doesn't have it already, so do the Role creation...
                //create the admin role
                Role.create({
                  name: 'admin'
                }, function(err, role) {
                  if (err) throw (err);
                   //make admin
                  role.principals.create({
                    principalType: RoleMapping.USER,
                    principalId: users[0].id
                  }, function(err, principal) {
                    if (err) throw (err);
                  });
                });
            }
        });

By:

Role.create({
      name: 'admin'
    }, function(err, role) {
      if (err) throw (err);
       //make admin
      role.principals.create({
        principalType: RoleMapping.USER,
        principalId: users[0].id
      }, function(err, principal) {
        if (err) throw (err);
      });
    });

Drop the Role collection: db.Role.drop() and execute Loopback again.

Note: I was doing the same assigment and worked for me.

Upvotes: 1

Related Questions