1056

Authorization: userOwnedSegment

Comments for “Authorization: userOwnedSegment”
 

Posted by Brian Peters on Saturday 8th July 2023 at 21:47 GMT

After watching the video about this subject, I understood that the INT being passed with the GET request of the "Find One" endpoint will always be:
- in the 4th segment
- the INT that will match against the mandatory "id" column of the table

Any changing of the "userOwnedSegment" params "column" and "segmentNum" did not allow me to match the 4th segment of the request url against any other column in the table.

I did have some odd results when changing the params:

"authorization": {
      "userOwnedSegment": {
        "column": "id",
        "segmentNum": 4
      }
    }

This produced the expected results of only being able to query records matched to my trongate_user_id via the proper token.


"authorization": {
      "userOwnedSegment": {
        "column": "message_read",
        "segmentNum": 4
      }
    }

This results in "invalid token" for every record attempted... as expected I assume.
Column "message_read" is a TINY_INT column I added to the table, putting a column that does not exist results in error.

"authorization": {
      "userOwnedSegment": {
        "column": "message_read",
        "segmentNum": 2
      }
    }

This however resulted in me being able to retrieve ALL records by the ID being passed in segment 4, any "segmentNum" other than 4 let me have any record I asked for regardless of "trongate_user_id"

It gets even more weird, it seems that any other existing column I use, for example I added a "sender_user_id" column, and if I try this:
"authorization": {
      "userOwnedSegment": {
        "column": "sender_user_id",
        "segmentNum": 2
      }
    }

I get "invalid token" every time.

I am just an amateur and don't know if there is anything that could be exploited there, but I am wondering that "userOwnedSegment" authorization should just be "userOwnedRecord" with no additional params, because the "column" and "segmentNum" seem to be hard coded and mandatory that the column be "id" and the segment number be 4.

Is there something I am missing?
Level One Member

Brian Peters

User Level: Level One Member

Date Joined: 22/05/2023

Posted by DaFa on Sunday 9th July 2023 at 00:39 GMT

G'day Brian and welcome to Trongate!

I removed your second post as it was a double-up of sorts - and yes, we review posts because in the past we had people with malicious intent tying all sorts of rubbish.

I've pasted your second post as it had a follow-up of value:
Don't know if these just get posted or if they are reviewed first and then posted if helpful, but in follow up to my previous question/post about the weird results I got with "userOwnedSegment" while using column of "message_read" giving me different results than any other table column.

That particular column is one that I added directly via phpMyAdmin and it was not coded in the module with the rest of the table columns as created by the Trongate desktop app.


I'm a little confused as was DC when he was trying to clarify this feature of the API - so I'm going to take a time out to review your question. If anyone else wants to try and solve this for Brian - please do.
Founding Member

DaFa

User Level: Founding Member

Date Joined: 30/11/2018

Posted by Brian Peters on Sunday 9th July 2023 at 05:13 GMT

Thank you for the reply.

I am not sure I have a real question there but ran into this issue while trying to familiarize myself with the framework.

The idea I had was for a user requesting unread messages, which leads me to a real question.

I added the following to the api.json of my messages module:
"Get New Messages": {
    "url_segments": "messages/get_new_messages",
    "request_type": "GET",
    "description": "Fetch all new messages for user",
    "authorization": {
      "roles": ["member"]
    }
  }

and the endpoint in messages controller:
function get_new_messages () {
        $this->module('members');
        $token = $this->members->_make_sure_allowed();
        $member_obj = $this->members->_get_member_obj($token);
        $sql = 'SELECT * FROM messages WHERE trongate_user_id=:trongate_user_id AND message_read<1';
        $sql_data = [ 'trongate_user_id' => $member_obj->trongate_user_id ];
        $messages = $this->model->query_bind( $sql, $sql_data, 'object' );
        json($messages);
        die();
    }

This results in retrieving messages that belong only to the user and have column 'message_read' < 1, 0 means not read, non-zero would be a read message.
This is not in a real project, just me playing around with ideas to learn the framework.

Would it be possible and useful if we were able to inject custom endpoints into Standard_endpoints, by adding into the api.json file as I did, and injecting the custom endpoint function into the Standard_endpoints so it could be called via /api/get_new_messages/messages?

It would maintain consistency across the app for api calls and prevent having to manually edit the Standard_endpoints.php which of course is a bad idea.
Level One Member

Brian Peters

User Level: Level One Member

Date Joined: 22/05/2023

Posted by Nicholo de Santi - Codex Realmz on Monday 10th July 2023 at 02:45 GMT

Afternoon, (sorry this is going to be long) TLDR: Use custom routing to achieve what you want to do without modifying the Standared_endpoint.php

I am unsure as to what you are asking or not asking, but let me take a crack at this see if this clears anything up for you.

The userOwnedSegment authorization feature in Trongate is intended to enable API endpoints to fetch records based on a particular segment in the URL, which aligns with the primary key column (typically id) of the table. Its purpose is to ensure that only the records belonging to the authenticated user can be accessed.

the usage of the column and segmentNum parameters in the context of the userOwnedSegment authorization feature:

The column parameter serves the purpose of specifying the column name used for matching records. By default, it is set to id, indicating that the primary key column (id) will be used for record matching. It is not meant to be used with arbitrary columns from the table but rather for identifying the primary key.

On the other hand, the segmentNum parameter determines which segment of the URL should be utilized for record matching. By default, it is set to 4, implying that the fourth segment of the URL will be used for this purpose. This assumption is based on the typical URL structure of /api/controller/method/segment1/segment2/segment3/{id}.
When it comes to the usage of the userOwnedSegment authorization, it is important to note the following:

Regarding the column parameter: The userOwnedSegment authorization feature is specifically designed to work with the primary key column (id) and is not intended to be used with other columns such as message_read. Attempting to use it with a column other than the primary key can lead to unexpected errors, such as the "invalid token" error you encountered.

Regarding the segmentNum parameter: The segmentNum parameter is specifically designed to work with the default convention of using the fourth segment of the URL for record matching. Changing the segmentNum value to a different number can result in unexpected behavior, as the framework relies on the assumption that the primary key segment is located at the fourth position in the URL.

It is important to keep in mind that the userOwnedSegment authorization feature is primarily aimed at providing a straightforward and secure approach to enforcing record ownership based on the primary key column. If you require more complex authorization logic based on different columns or segments, it may be necessary to implement custom authorization checks within your endpoint's controller method.

So for example if you wanted to have a Parent Module of Dashboard, and a Sub Module of Messages(modules/dashboard/messages), but wanted to call the unread messages for the member on the dashboard you would do so like this.

Create your Dashboard module with this structure modules/Dashboard/assets/controllers/views

In the assets/ dir place a file called api.json
with this code added along with all your others such as "Get By Post" etc:
"Get New Messages": {
        "url_segments": "dashboard/members/get_new_messages",
        "request_type": "GET",
        "description": "Get new messages in the Dashboard",
        "authorization": {
            "roles": ["members"]
        }]
        }

Then create your dashboard/controllers/Dashboard.php controller file with this code
class Dashboard extends Trongate
{
    public function index()
    {
        // Your custom logic for the Dashboard index page
        // ...

        // Load the view
        $this->view('dashboard/index');
    }

    public function get_new_messages()
    {
        // Call the function in the Messages module
        $messages = $this->module('messages')->get_new_messages();

        // Return the response
        json($messages);
    }
}


Then create your modules/dashboard/views/index.php
Now start to work on the submodule Messages

Create modules/dashboard/messages/assets/api.json
just like before add this to the other code with your "GET" calls:
"Get New Messages": {
        "url_segments": "dashboard/members/get_new_messages",
        "request_type": "GET",
        "description": "Get new messages for the authenticated member",
        "authorization": {
            "roles": ["members"]
        }


Create modules/dashboard/messages/Messages.php
class Messages extends Trongate
{
    public function get_new_messages()
    {
        $this->module('members');
        $token = $this->members->_make_sure_allowed();
        $member_obj = $this->members->_get_member_obj($token);
        $sql = 'SELECT * FROM messages WHERE trongate_user_id=:trongate_user_id AND message_read < 1';
        $sql_data = ['trongate_user_id' => $member_obj->trongate_user_id];
        $messages = $this->model->query_bind($sql, $sql_data, 'object');
        json($messages);
    }
}


I hope that clears things up! If you need more help please ask.
Level One Member

Nicholo de Santi - Codex Realmz

User Level: Level One Member

Date Joined: 16/01/2023

Posted by Brian Peters on Monday 10th July 2023 at 23:52 GMT

Thank you for that!
Level One Member

Brian Peters

User Level: Level One Member

Date Joined: 22/05/2023

×