Jump to content
thomasaull

Rest-API site profile

Recommended Posts

Thank you for the profile. 

I'm trying to move client vue part to another domain. In order to do that, i had to make a few modifications:

 

to Auth.php:

public static function preflight() 
{
	return "OK";
}

to Router.php:

header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Headers: Authorization, Content-Type');
.
.
  $r->addGroup('/auth', function (\FastRoute\RouteCollector $r)
  {
    $r->addRoute('OPTIONS', '', Auth::class . '@preflight');
.
.
  $r->addGroup('/test', function (\FastRoute\RouteCollector $r)
  {
    $r->addRoute('OPTIONS', '', Auth::class . '@preflight');

and change  axios.defaults.baseURL

but after login it stays as "guest" (User logged in: guest)

It seems that it's impossible to use session (wire('session')->login) in that situation.

 

Could you advice how to pass and re-use, for example, user ID, bypassing processwire session (may be through encoding it with JWT)?

 

Nikolay

 

 

 

Share this post


Link to post
Share on other sites
On 9/6/2018 at 9:30 AM, nicolant said:

 It seems that it's impossible to use session (wire('session')->login) in that situation. 

while the wire('session')->login() should work for this request, it is likely the session is already destroyed on the next one. For this case it might be feasible to store the user id in the jwt payload (like you suggested). Since I'm going to have this case in an upcoming project, I gave it a try this morning. Please check the following commit for the changes I did: https://github.com/thomasaull/RestApiProfile-Src/commit/2dbdc79aa952bece6926dbee896de0a4f434bb6a

I didn't test it with different domains though, so I'd be thankful if you could report back if it works for you! 🙂

Share this post


Link to post
Share on other sites

Hallo, I wanted to test this site profile and cloned PW 3.0.98 from git. Then cloned the site profile repo and installed PW without any issues. I issued the 2 composer commands to install dependencies.

Environment: Apache with PHP 7.0.29 FPM/FastCGI.

When I try to access api/test, I get the following error

Screenshot_2018-09-08_12-05-43.thumb.png.b6d56abe13abbda1b3c51a78fd7b55a4.png 

Looks like a namespace issue. I didn't change namespaces on any of the files included in the profile. My config.php is not namespaced.

Does anyone have an idea how I can overcome this?

EDIT: apache_request headers became available under FastCGI since 5.4.0 according to http://php.net/manual/en/function.apache-request-headers.php 
EDIT2: After some more investigation I found https://bugs.php.net/bug.php?id=70025. So it seems apache_request_headers is still not supported in PHP 7.0 FPM/CGI environment.
I added templates/inc/functions.php with contents of https://gist.github.com/rmpel/11583cfddfcc9705578428e3a2ee3dc1 and added require "{$config->paths->templates}inc/functions.php"; to api.php
This solved the problem :)-
 

Share this post


Link to post
Share on other sites
On 9/7/2018 at 12:42 PM, thomasaull said:

while the wire('session')->login() should work for this request, it is likely the session is already destroyed on the next one. For this case it might be feasible to store the user id in the jwt payload (like you suggested). Since I'm going to have this case in an upcoming project, I gave it a try this morning. Please check the following commit for the changes I did: https://github.com/thomasaull/RestApiProfile-Src/commit/2dbdc79aa952bece6926dbee896de0a4f434bb6a

I didn't test it with different domains though, so I'd be thankful if you could report back if it works for you! 🙂

It remembers userId after login, but not on next reload of content, when   if(wire('user')->isGuest())  in Auth.php returns true.

Instead in auth() it should again read userId from token, but since $decoded variable is available only in Router...

 

EDIT:

It seems that retrieved JWT should be kept in sessionStorage entirely client-side. In order to do that I'd have to use VuexPersist plugin.

I'd have to move setting of authorization header (in my case, axios.defaults.headers.common['Authorization'] = 'Bearer ' + this.$store.state.jwt) from mutations.js to Content.vue. Not sure though that it's an elegant way.

I forked your repo with modifications here:

https://github.com/nicolant/RestApiProfile

 

Share this post


Link to post
Share on other sites

The auth() and login() functions are usually just used once to login a user and obtain an JWT token. The token is currently stored in vuex and will be lost on reload. The /client folder is also just intended to get you started and give you a general idea how the jwt login process could work. Anyway I think you figured it out by now 😉

Share this post


Link to post
Share on other sites
On 9/8/2018 at 12:11 PM, gebeer said:

Hallo, I wanted to test this site profile and cloned PW 3.0.98 from git. Then cloned the site profile repo and installed PW without any issues. I issued the 2 composer commands to install dependencies.

Environment: Apache with PHP 7.0.29 FPM/FastCGI.

When I try to access api/test, I get the following error

Screenshot_2018-09-08_12-05-43.thumb.png.b6d56abe13abbda1b3c51a78fd7b55a4.png 

Looks like a namespace issue. I didn't change namespaces on any of the files included in the profile. My config.php is not namespaced.

Does anyone have an idea how I can overcome this?

EDIT: apache_request headers became available under FastCGI since 5.4.0 according to http://php.net/manual/en/function.apache-request-headers.php 
EDIT2: After some more investigation I found https://bugs.php.net/bug.php?id=70025. So it seems apache_request_headers is still not supported in PHP 7.0 FPM/CGI environment.
I added templates/inc/functions.php with contents of https://gist.github.com/rmpel/11583cfddfcc9705578428e3a2ee3dc1 and added require "{$config->paths->templates}inc/functions.php"; to api.php
This solved the problem :)-
  

@gebeer you can also try to replace apache_request_headers() with $_SERVER which should also work. This way you don't need the any additional functions

  • Like 1

Share this post


Link to post
Share on other sites

Also just as a heads up, I'm in the process of converting this site profile into a module, since I'm struggeling to keep it up to date on my sites and thus should be much easier to update in the future

  • Like 4

Share this post


Link to post
Share on other sites

@thomasaull Great that you are converting this into a module. It would be a muc better fit. That way we can add api funtionality to any site easily. Actually, I was thinking about converting your site profile to a module, too 🙂

  • Like 1

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By VeiJari
      Hello forum,
      This is really a weird one, because front end editing works in a earlier website we did to a customer. 
      When I check the source code for current website it does initiate front end edit: 
      <span id=pw-edit-1 class='pw-edit pw-edit-InputfieldPageTitle' data-name=title data-page=1021 data-lang='1017' style='position:relative'><span class=pw-edit-orig>Tekijät</span><span class=pw-edit-copy id=pw-editor-title-1021 style='display:none;-webkit-user-select:text;user- select:text;' contenteditable>Tekijät</span></span>  But when I double click nothing happens (yes I'm 100% sure I'm superuser and logged in)
      I also tried to apply the front end with other methods than:
      $page->edit('title'); But didn't work either.
      We are using jquery 2.2.4, so it should not be a problem.
      Is this a bug related to current master or something else?
      Someone else having this problem as well?
    • By jom
      Hi everyone
      It seems that I don't fully understand the wireTempPath() function and I need some help.
      I use wireTempPath() to create a new location in assets/cache/WireTempDir and than copy a pdf from the assets/files/page folder to the new folder. I want the file to be accessible only for a limited time, that's why I use wireTempPath.
      The file seems to be copied to the right location, but gets deleted right afterwards, according to 
      As mentioned in the topic above, 
      $wireTempDir->setRemove(false); prevents the file to be deleted. But I like the file to be automatically deleted after a few days. So, how can I do that?
      My code so far (everything works, but the automatic removal of the tempDir folder):
      //generate and show download link $folder = time(); // timestamp as temporary folder $maxAge = (int) $settings->options_downloadlink_valid_hours * 3600; //tempDir wants maxAge as seconds $options = array( 'maxAge' => $maxAge ); $wireTempDir = wireTempDir($folder, $options); $wireTempDir->setRemove(false); $src_file = $page->ebook_download->filename; // Create a new directory in ProcessWire's cache dir if(wire('files')->mkdir($wireTempDir, $recursive = true)) { if(wire('files')->copy($src_file, $wireTempDir)){ //get subdirs from tempDir: $pos = strpos($wireTempDir, "WireTempDir"); $subdir = substr($wireTempDir, $pos, 100); $out .= "<p><a href='" . wire('pages')->get('template=passthrough')->httpUrl . "?file=" . $subdir . $page->ebook_download->basename . "' target='_blank'>$page->title</a></p>"; } } I appreciate any ideas - thanks!
      Oliver
    • By VeiJari
      Hello forum, this is my first security related post, so I'm a bit of a newbie.
      I understand that when I have direct front-input from user I should sanitize the input, but how about when I use a secret key for showing a API for a third-party supplier? Should I sanitize the input->get() key?
      I've tested this issue and I tried ?key=<?php echo $page->field; ?> And without adding any sanitization it comes back: /?key=<?php%20echo%20$page->field;%20?>
      So can I rely on this, or should I still use $sanitizer just in case?
       
      Thanks for the help!
    • By EyeDentify
      I have been experimenting with the new $page->meta() method and find it useful.

      Once i figured out that the data i "save" with it is tied to the page where i called the method from.

      So this is not obvious at least not for me in the documentation:
      https://processwire.com/api/ref/page/meta/
       
      So i just wanted to share that revelation with the community so you don´t get as confused as i was.

      Happy Coding Everyone.
    • By louisstephens
      Going through my long quest to get better with ajax and utilizing the api, I have hit yet another roadblock. I currently have a form with an image field (thanks to flydev for getting that sorted), "title" text input, and a select field set to multiple. In my ajax call, I added in:
      tags = $("#select-tags").val(); form_data.append('tags', tags); $.ajax({ type: 'POST', data: form_data, contentType: false, processData: false, url: '/ajax/upload-preview/', success: function(data) { console.log("Woo"); }, error: function(xhr, ajaxOptions, thrownError) { alert(xhr.responseText); } }); And in the ajax template: 
      $tags = $sanitizer->text($_POST['tags']); $image = $sanitizer->text($_POST['image']); $p = new Page(); $p->template = "preview"; $p->parent = $pages->get("/previews/"); $p->name = $title; $p->title = $title; $p->tags = $tags; $p->save(); If I select a "tag" from the select input and submit, it does indeed add it to the Page Reference field in the backend. However, this does not work with an array being passed to it of multiple options.

      So it does appear that my ajax call is trying to submit multiple options, but I am really just unsure how to get these two added in. I saw in other forums posts of add($page) and even add(array()). Do I need to handle this js array differently or do  I need to foreach through the $tags to add it like:
      foreach($tags as $tag) { $p->tags->add($tag); $p->save(); } I tried this approach, but apparently I am still missing something.
       
      Edit:
      I was doing some tweaking, and I know I can split the js array out like:
      for (i = 0, len = tags.length; i < len; i++) { console.log(tags[i]); } However, I am not sure then how to handle the POST in php if I were to split it out.
×
×
  • Create New...