week of 17 jun

17 Jun 2019

17 jun

I’m quite exhausted from my weekend in Indiana, but this ish has to get going. If I don’t figure out this stupid userGroupsAdmin nonsense in the next few days, I’m going to pull my hair out.

Right off the bat, I decided to take a look at what the live /manage-user-groups route has going on in the console since I’m already logged out after the weekend. It gave me a 401 (Unauthorized) for the /users/me endpoint, which is not surprising. But it doesn’t match the error in the docker build: net::ERR_CONNECTION_REFUSED. Also, the live site still generated a ualibweb.Token that is showing up in window.localStorage even though no one is logged in. Oddly, it does have the WP_DATA_USER_118 in localStorage, too, so maybe that’s a cookie/cache situation?

No matter who I log in as in the docker site, the localStorage remains WP_DATA_USER_1. I’ve logged in as me, as Boris, and Andrew… no difference. I wonder how I can change that? I’ve tried deleting cookies, hard reloading the cache… nothing. As Andrew, it should have me listed as WP_DATA_USER_11, but nope. Then again, I did well and truly screw something up when I imported this user table and erased my original admin account. I might need to just reinstall wordpress and add the wp_users and wp_usermeta tables after instead of completely wiping.

I reinstalled wordpress using the database prefix wp2_ in the wp-config.php file. Then I added Andrew as a user to the new install. Still getting the same weird localStorage nonsense and ERR_CONNECTION_REFUSED in the console about /users/me… so it wasn’t the messed up users table that was causing the issue in the other one. The problem there was that I couldn’t make myself an administrator once I deleted my old admin account, so I couldn’t get to the backend. :joy:

Back to square one, I guess.

Next plan: copy all WP files directly from live server and export all WP data, put that stuff in a new docker container and see what happens. I’m very tired of building this thing, but maybe if I’m running the production version, there will be some setting that switches on that I’m missing?? Let’s hope.

I’m in the middle of testing the docker build on my laptop (where I plan on working on the 1-1 build of the live site), when I stumbled up on a new mystery: even though I added Andrew as a user, the /users endpoint still only lists me as a user. Where is Andrew?? …after a Google, it seems this is on purpose. If a user hasn’t published any posts, they are left out of the users endpoint.

Then I tried to go to my specific user ID endpoint: /users/1 and got a WP error page. Here’s the log:

[Mon Jun 17 18:53:25.001707 2019] 
[php7:error] 
[pid 735] 
[client 172.30.0.1:43124] 

PHP Fatal error:  Uncaught Error: Call to undefined function gGetUserData() in /var/www/html/wp-content/themes/roots-ualib/functions.php:52

Stack trace:

#0 /var/www/html/wp-content/themes/roots-ualib/functions.php(83): createToken(Array)

#1 /var/www/html/wp-includes/rest-api/endpoints/class-wp-rest-controller.php(395): {closure}(Array, 'token', Object(WP_REST_Request), 'user')

#2 /var/www/html/wp-includes/rest-api/endpoints/class-wp-rest-users-controller.php(949): WP_REST_Controller->add_additional_fields_to_object(Array, Object(WP_REST_Request))

#3 /var/www/html/wp-includes/rest-api/endpoints/class-wp-rest-users-controller.php(422): WP_REST_Users_Controller->prepare_item_for_response(Object(WP_User), Object(WP_REST_Request))

#4 /var/www/html/wp-includes/rest-api/class-wp-rest-server.php(946): WP_REST_Users_Controller->get_item(Object(WP_REST_Request))

#5 /var/www/html/wp-includes/rest-api/class-wp-rest-server.php(329): WP_REST_Server->dispatch(Object(WP_REST_Request))

#6 /var/www/html/wp-includes/rest-api.php(309): WP_REST_Se in /var/www/html/wp-content/themes/roots-ualib/functions.php on line 52

The sGP/functions.php weren’t loading, which is what was causing my WebApps admin icon disappearance. It’s back now and so is the user ID endpoint, but I’m still not setting the ualibweb.Token in localStorage. What’s WEIRD though, is that my /users/1 endpoint has a token set. Like, the object has a key called “token”. How?! Where is that being injected? Why? And what does it do?

I’m willing to fall down that rabbit hole, and honestly, I probably should. Soon.

BUT. I also starting going through the wordpress functions.php and found a bunch of fascinating WP API stuff. I’d rather look into that right now.

On line 51, the whole rest API thing gets kicked off with a call a function from sGP/functions.php. THIS IS WHERE THE TOKEN IS BEING CREATED. Big news.

There’s then a function that checks if a user is logged in when they try to access the rest API. I’m a little confused by how this function actually works, because if all it’s doing is checking for logged-in status, then why does my WP install think I’m not logged in? I definitely am.

But it’s the NEXT function that is the most interesting to me: for whatever reason, it’s rewriting the endpoint /users/$id to /users/me. Why?! It also takes the token created from that first function and adds it to the endpoint. Like… these are clearly the functions I need to be focusing on.

TODOs:

gGetUserData

Just had an “excuse me, WHAT” moment in my office. I’ve been echoing/var_dumping variables/functions from this sGP/functions file, and decided to just dump what gGetUserData($userData) outputs. On Andrew’s login, it’s returning:

array(3) { ["group"]=> int(0) ["ip"]=> string(10) "172.30.0.1" ["login"]=> NULL }

Which I just var_dumped from a different function gGetUserGroupWP his group should return 2047. 0?!? And login should be amparker8 not NULL. So something in that function is busted. Database connection?

Whyyyy does this function set the user group to 0 right off the bat? I’ve been var_dumping all up and down this function, and I can see no good reason to do that. How is this working in production?!

Alright. These two function files are wrapped up in each other. Imma need to print them out to see how everything connects. It looks like $userData (which is fed into a few different functions) is created in the wp functions.php file, but then used in the sGP/functions.php file. But only when the API is involved? Which seems odd.

These functions are doing what they say they do (I mean, I assume almost all of them are and I just don’t understand what that means yet): createToken in wp functions that creates a token for the rest_api_init later in the file is, indeed, creating a token. Even my /users/1 JSON shows the token it created for me. So why is that token not being saved to localStorage for the headers? And why doesn’t the /users/me path think I’m logged in? I checked that preg_match and it’s returning 1, which means the API route found a match.

Also: The routes don’t think andrew’s username exists. I tried /users/11, /users?slug=amparker8, /users?nickname=amparker8 and nothing. Is the database not connecting correctly? Problem solved: I created a post under Andrew’s name. Surprise, surprise, he’s showing up in the JSON data now. So so strange.

Back to my new dilemma: If the $userData info is faulty, and then that data is being turned into a token that is then encoded, is it any wonder that the Authentication is failing? I still don’t understand why the headers aren’t being set… there’s a token after all, shouldn’t it use it even if it’s not right?

Today was one of those days where I made a ton of progress but it does not look or feel like it. Hopefully I will wrap this up tomorrow. If not, I’m not sure what I’ll do.

18 jun

It’s 10:40, which means I’ve been hacking away for about 90 minutes. After talking to Scott this morning about how weird it is that I’m getting net::ERR_CONNECTION_REFUSED in the console instead of a 401 or similar, he agreed that it’s weird and I should look into that. So I googled.

Yesterday, I thought it was a problem with the endpoint users/me, so I started by changing that to just users, but the problem persisted. It didn’t matter which API endpoint I tried to access, it wasn’t having it, and kept giving me the same error. So something else was going down. When I looked at the console error, it suggested the problem was occurring at the function that sends the XHR request xhr.send(post || null), so something deeper is going on here.

Googling the error message lead me to believe this might be a CORS issue, but then I chatted Scott about it and he thinks its SSL (a google confirmed this is probably the case):

chat with scott about http vs https error

Boooooo. So now I get to figure out how to add an SSL certificate to my docker container? Or localhost? WHYYYYY :weary:

Turns out, yes. This is definitely an issue. Let’s Encrypt has an entire page about how/why this is a thing. Looks like I’ll be generating a certificate for myself so my localhost can be served over secure HTTP. Lord almighty.

Hokay, so. Steps I followed (for future me):

<VirtualHost *:80>
  DocumentRoot "/var/www/html/"
  ServerName localhost
  SSLEngine on
  SSLCertificateFile "/etc/apache2/ssl/localhost.crt"
  SSLCertificateKeyFile "/etc/apache2/ssl/localhost.key"
</VirtualHost>

Had to rebuild the docker build: docker-compose up --build because of a typo in the apache config file, but it seems like everything is in the right place because it built!

Went to localhost, and got a ‘Bad Request’ error, which makes sense. I was trying to access at http site: “Your browser sent a request that this server could not understand. Reason: You’re speaking plain HTTP to an SSL-enabled server port. Instead use the HTTPS scheme to access this URL, please. Apahce/2.4.25 (Debian) Server at localhost Port 443.”

I’m down with most of this message, since I was indeed trying to access it via HTTP. Buuuut what’s this port 443 business about? I’m exposing port 80.

I tried adding EXPOSE 443 to my Dockerfile and -443:443 to the ports list in docker-compose.yml. Went to https://localhost and now I’m getting “This site can’t provide a secure connection, localhost sent an invalid response. ERR_SSL_PROTOCOL_ERROR” so I’m assuming I set something up wrong.

Thanks to a very helpful stack overflow, it turns out I didn’t know that http is served in port 80 but https in served in port 443. Changed that in my 000-default.conf, Dockerfile, and docker-compose and TADA!

IT’S LOADING AND SO IS THE MANAGEMENT APP!! :tada::tada::sob::grin:

There are more error messages waiting for me in the console, but I’m going to take this moment to enjoy a lindor truffle.

I hate that the answer was so simple but it took me a week to find it. The good news is that I now know the ins and outs of this management app and JWT pretty well, and that should save future-me some time when we change all these apps to wordpress plugins later.

Latest error situation: in the manage users app, it gets as far as “WP user list received” console log (if the live site is to be believed, that is console.log message 4/6) before stopping. Instead of continuing on its merry way, we get a data object returned to the console, giving us the same “data” that we’ve seen from the API endpoint userGroupsAdmin/api/users: ‘Error: could not retrieve users.’ I find this odd because if you try to access this endpoint on wwwdev2 or even lib.ua.edu, you get the exact same error message. So… why does this not affect the live site but for whatever reason is holding up the docker site? Back to the drawing board.

TODOs:

19 jun

My morning dabbling had me going through the apps accessible in the WP backend. The alerts app was loading and presenting me with option to create a new alert, which I tried to do. It gave me an error I recognized: “Session expired! Please update your browser window by pressing F5 or clicking Refresh button.” I’ve seen this in one other place: userGroupsAdmin/index.html. The error isn’t exactly the same, so I don’t think it’s coming from the same place, but I can’t help but think it’s connected to the user groups app in some way.

So what exactly is happening? There’s a function, .createAlert that hits the alertFactory.postData function, which tries to return an http POST method to the url https://localhost/alerts/processData.php?action=3. This makes no sense to me because the alerts API only has GET methods. Sooooo what’s going on here? And if the alerts API only has get methods, how are new alerts created??

I went to https://localhost/alerts/processData.php?action=3 in the browser and got the same error message. So what/where is this processData.php????

There are whole files in these PHP apps called processData.php. How did I miss this?? Time to investigate what these do! I’m assuming they process data (surprise!) but what does that involve? (Holy shit, howwwwww did I miss this?)

After a morning of var_dumping, echoing, and console logging, I feel more lost than I did when I started this day.

This all comes back to the damn global sGP/functions.php shit. I DO NOT UNDERSTAND how these functions and the WP shit interact. At all. It seems like the php functions should work independently of the WP stuff, but it pretty much hinges on whether or not the user has permissions to act within/on an app. But you can’t figure that out without a WP login. But maybe that’s just a webapps_userGroups thing?? Either way, those JWTs are checking for Authorization headers, but I don’t think those are set until you get the angular front-end stuff in bower_scripts.js (the AuthInterceptor, which relies on AuthService). I just… don’t understand. And I want to scream.

Another baffling thing: so many of these functions rely on other functions not being falsey, but all of them return false???

I took a walk, which I desperately needed. I thought through my anger, and I definitely need to come up with a systematic way of drilling down through this app. Since I’m already in the alerts app, I’m going to stay here and go line-by-line, function-by-function and map what they all do and what the outcome is. It’ll probably be slow and very boring, but since these are global functions, they are used over and over and it’s kind of imperative for me to understand what they’re doing. I would love to write tests for each of them, but I don’t actually know how I would do that at this moment, so I won’t.

20 jun

Yesterday went much better after I started working through the alerts app functions and mapping what did what. I think I might actually be able to figure this out!

The construction noise is very bad in my office today. Are they drilling directly under me?! I might need to go find somewhere else to work, so I’m currently trying to figure out how to version control this project so I don’t have to transfer files back and forth on a usb stick. It’s like… a half a gig, so I don’t think I can put it in box. And my project contains another github repo, so that would have to be a submodule that I would then need to build later, which sort of defeats the purpose of what I’m doing. I need exactly what I have on this computer to be on my other computer. Hmm…

angular confusion

I’m trying to wrap my brain around how this manage module does what it does. I probably need to watch some youtube videos on http/httpProvider/interceptors because I don’t think I quite grasp what’s going on here.

I’ve been looking at this code for about a week now, but I think I only just put together that the httpProvider/interceptor that are set up in the config of the common.manage module affect every single request made through the factories in this module. I didn’t realize that when something is using $http service, it also runs through the $httpProvider? At least, I think that’s what’s happening? And this is where the token and auth headers are being set, so this is definitely where I need to be focusing because I can’t get those damn auth headers to show up in my request headers! Which is odd, because the token does show up. So. :woman_shrugging:

A few youtubes later, and yes, that interceptor deal happens with every http request. So time to figure out why the auth headers aren’t being sent. I really thought I ruled this out before, but I guess I didn’t understand what was happening.

I did it! Lots of ideas finally coalesced in the ol’ noggin, and I realized that an if statement with my poorly constructed URL was holding everything up. I needed https://localhost/ in the conditional and I had localhost/. Of course it was a filepath problem! The bane of my existence. I added a new alert to the system and it appeared on the homepage. One app down, seven to go!

Bebopping my way through the erCarousel UI, when I realized there’s a “pending approval” label on the slide I just added. That sent me on a 90-minute journey to figure out why this app didn’t think I was considered “admin.” After console.logging all the data outputs, I was pretty baffled. I had to go back to the sGP/functions.php before I figured it out: some of the apps have admins tables in their database! I believe those apps are news, hours, and erCarousel. There could be more. Once I added myself to the erCarousel admins table, I can now approve slides in the erCarousel app, so that must be the case!

Note to self: When you’re (inevitably) writing the documentation for this later, make sure you mention something about these unknowable tables!

forms

So this “forms” app: It’s working my docker version, but Rudaina let me know about a week ago that the live version wasn’t loading. I had trouble looking at the logs last week, so I let it go, but since I’m in the throes of this app-checking stuff right now, I figured I’d look into that issue now.

Turns out: Fatal error: Allowed memory size of 134217728 byes exhausted. So… we have too many forms for PHP to be able to handle at once? That database has 12k+ form submissions in it, so it makes sense that the API call is being blocked because of a memory error. Rudaina and I both think it would be fine to archive the older submissions (they go back to June 2015!) to free up memory until we come up with a new forms system.

So much success today! I checked off five of the 11 apps from my list! Now that things are clicking, I should definitely be able to finish this up by next week. Huzzah! :tada::tada::satisfied:

21 jun

First day of summer and also a Friday. It’s going to be a good one! …even if it’s going to be 93 degrees but feels like 100 on my bike ride home. :grimacing::sweat::sunglasses:

Working on the software app, and I must say: these computer maps, yo! :flushed: I do not want to recreate these. Someone probably had a great time creating it, but I bet it’s complicated. From what I can tell, though, the maps in the backend of this app are not being used any where on the site. There are other maps: some that are static and show where computers are located, then some that show which computers are available for use… but not these??

All the apps are working. Which means no issues with PHP 7.2! :tada::tada:

plugins

Next up: make sure all the plugins we use can be upgraded with no issue. This will involve figuring out which plugins are actually being used and what they’re doing. There are 22 active plugins on the live site, but only 6 actually need updates, so I guess that’s a good thing.

After giving our apps a cursory glance through, it looks like I’m going to have to export our pages and some other content in order to really test what these do.

content import

After importing (some of) the pages from our live site, it seems like some of wordpress hooks are messed up… I’m not sure if they’re messed up for the live site or if this has something to do with the latest version of WP. The php logs are only showing them as warnings, so it’s not a huge deal, but I’d rather not clog up the log files with something that can be easily fixed.

I’ll look into that next week.