1

First Context:

I am making a JS application that needs to call an api.

The application is a form full of multiple choice select elements. Depending on the selected elements data is sent to the api. The api should return an article's full text.

I have the following code which works. (no logic being done yet but I can do that later)

<?php

include ("/components/com_content/models/article.php");

class WdtoptionsApiResourceOptions extends ApiResource
{

    public function post()
    {   
        $data = new \stdClass;
        $data = json_decode(file_get_contents("php://input"));
        
        $result       = new \stdClass;
        $result->name = "WDTOptions Test";
        $result->id = 6;
        
        JModelLegacy::addIncludePath(JPATH_SITE . '/components/com_content/models' );
        
        $article = JModelLegacy::getInstance( 'article', 'ContentModel');
        
        $body = $article->getItem(6);
        

        $result->optionlist = $body->introtext . $body->fulltext;
        $result->postData = $data;
        
        $this->plugin->setResponse( $result );

    }
}
?>

The issue is that the article's text is returned by the api regardless of whether the user is logged into my site. This means that third parties could run their own apps off my api. They could also probe my api to work out how to use it. As my business depends on selling licences to this app I want to avoid that.

It has occurred to me that I could solve the problem by having my api output a hyperlink to the article and then having my front end call the article separately by a separate AJAX call. However this seems clunky and generally poor practice.

Is there way to have the ACL from the site apply to the API itself? I don't really want to use the JWT authentication process unless I have to.

Just to clarify I'm not expecting full code answers. Psudocode or overview is fine.

4
  • I have explored most of the available options at this point. I would like to ask a slightly different question now I know more about the problem. Should I edit or create a new question @mickmackusa ?
    – Huw Evans
    Jan 16, 2021 at 19:42
  • Your choice. With no comments or answers, there is no harm in editing. Deleting this one and asking a new one is absolutely fine too.
    – mickmackusa
    Jan 16, 2021 at 23:47
  • If you do decide to ask a different question then it would be really helpful to have a diagram showing the context of how your code interacts with the Joomla site. Eg does your js code sit within a browser or is it node js on a server? If it's js code on a joomla site page, I'm not really sure why you can't just use joomla authentication plus Joomla form token verification, and check the Access field in the article. Jan 19, 2021 at 16:20
  • @RobbieJackson This is JS code on a joomla site page. I am not familiar with the method you describe but it does sound like exactly the solution I need.
    – Huw Evans
    Jan 19, 2021 at 16:25

1 Answer 1

2

If your js is attached to a joomla page then you can get your users to login to joomla in the usual way. Then when your js executes an ajax call to the server, because the browser sends the session cookie in the http request, joomla knows if the http request is associated with a logged-in user. So inside your server code handling the ajax request you can do

use Joomla\CMS\Factory;

$user = Factory::getUser();
$accessLevels = $user->getAuthorisedViewLevels();

(See User API Guide).

Then you can check if the user has access by checking if the Access field associated with the article is present within the $accessLevels of the user. Some of your articles may have public access, so you may wish to show those to visitors who aren't logged in.

Another aspect to implement is to include the Joomla form token within your form using (in the joomla layout file):

<?php echo JHtml::_('form.token'); ?>

and include this html input field in your ajax request.

Then in your ajax request handling code:

if (!JSession::checkToken('get')) 
{
    echo new JResponseJson(null, JText::_('JINVALID_TOKEN'), true);
}

This means that anyone trying to copy your ajax request from elsewhere will have the request rejected.

There is documentation on including js code within joomla in Adding Javascript and CSS to the page and also worked examples in the Joomla MVC Tutorial steps Adding a Map and Adding Ajax.

3
  • This is exactly the kind of solution I was aiming for. Thank you so much. Just one question though about this: Where can I find the 'joomla layout' file you are referring too?
    – Huw Evans
    Jan 19, 2021 at 18:29
  • To present your form you'll have to develop a little joomla component. The multi-step Joomla MVC tutorial explains how to do this, but may be overkill for your needs. I suggest you look at docs.joomla.org/Basic_form_guide, and follow the paradigm within the Sample Form 2 section. Basically Joomla adopts a model-view-controller approach and splits the 'view' into a view file (which collates the data items which are to be shown on the web page) and a layout file (which contains the html and outputs the data in php echo statements). Jan 19, 2021 at 19:01
  • Ah I see, I am actually generating the form dynamically using JS so I guess I can't implement that bit. Anyway you have answered the question. I'll mark it accepted.
    – Huw Evans
    Jan 19, 2021 at 19:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.