Stuff I'm Up To

Technical Ramblings

JIRA, Confluence and Nginx — September 15, 2018

JIRA, Confluence and Nginx

With Atlassian Jira Software and Confluence installed onto the same server I thought I’d investigate setting things up so we don’t have to use the default TCP port type of access over HTTP. instead let’s setup a reverse proxy using HTTPS over TCP 443 that forwards to the TCP 8080 and 8090 ports.

The aim is to get Jira accessible as https://jira.domain.local and Confluence as https://jira.domain.local/confluence.

Continue reading

Advertisements
Verint Online Forms — August 30, 2018

Verint Online Forms

We’re new to this and trying to integrate a form solution with our Lagan CRM system. We have a corporately installed test and production system for forms, but it get frequent usage by many non-IT related staff, so I thought about deploying our own dev system.

The forms products are pretty much Jetty programs with a database requirement. Looking at the config files for the initial deployment package they are looking for either H2, Oracle or MSSQL. That means our only real dev option is H2.

Step 1 – Install the H2 database

Download the platform independent zip from http://www.h2database.com/html/main.html and extract it into a suitable location.

Make sure you have a $JAVA_HOME environment variable set, and ensure you have a Java JDK (not just a JRE) installed. On my Debian system I set it to the default java instance (which just happens to be Java 10):

$ export JAVA_HOME=/usr/lib/jvm/default-java

Then run the H2 program:

$ cd h2/bin
$ sh ./h2.sh

This fires up a browser session and gives you an icon in the tray if you’re running a windowed environment.

Step 2 – Install dforms

Extract the dfoms zip file.

Edit the config.sh file in dforms-x.x.x/bin as necessary. The only changes I made to this one was the jdbc user and password. I prefer not to use defaults.

Run the program:

$ cd dforms-x.x.x/bin
$ sh ./Run.sh

We then have a running dforms program listening on the default port 9081. You can use your browser to visit it at http://localhost:9081/auth/login and logon using the defaults Admin/Admin credentials.

Step 3 – Install dforms-leadapter

Extract the dfoms-leadapter-x.x.x zip file.

Edit the config.sh file in dforms-leadapter-x.x.x/bin as necessary. I made a few more changes to this one, again the jdbc user and password – it is a different database than the dforms one and there are two of them in this config. But also the flweb_lagan_uri and flweb_user and flweb_password to match our environment.

Run the program:

$ cd dforms-leadapter-x.x.x/bin
$ sh ./Run.sh

We then have a running dforms-leadapter program listening on the default port 9082. You can use your browser to visit it at http://localhost:9082/auth/login and logon using the defaults Admin/Admin credentials.

When is a Question Mark not a ? — August 29, 2018

When is a Question Mark not a ?

That’s a morning of smashing my face on the desk again. I deployed my dev program onto a production system and then started crying as it stopped working as it should.

It seemed that none of my query string parameters were making it through to the controller. I called up some debugging and dumped out my $request and $request->all() etc. and discovered that the parameters although shown in the browser dev window went AWOL between server and controller. On my dev environment it all acted as it should.

So there must be something different. PHP v7.2 on dev and v7.0 or production maybe? No, much simpler than that. None of the Laracasts and Laravel related Googling pulled up any particular clues. It wasn’t until I looked at Nginx and parameters not being passed to PHP that I got a hit.

https://serverfault.com/questions/685525/nginx-php-fpm-query-parameters-wont-be-passed-to-php

The answer was as simple as adding in the $is_args into my Nginx virtual server config.

location / {
  try_files %uri $uri/ /index.php$is_args$query_string;
}

Up until now I guess I’ve been using routing with the parameters as part of the URI. Now I’m using some query string parameters I need to put in the ?, which is the $is_args variable.

So why not a problem in dev? Because I’m not using Nginx, I just use artisan serve to debug my development program.

Postman is Awesome — August 21, 2018

Postman is Awesome

I’m in the process of testing and documenting my API’s and up until yesterday I’d only used postman to test my responses gave me something back. But it’s capable of so much more!

I can use it to generate the documentation for each call I make, publish it online and share it with colleagues.

But I can also use it to carry out unit tests on my API calls. Which is awesome.

Then I find I can use globals and environment variables to migrate my tests and documentation between development and production systems… which is even more awesome.

Continue reading

Postman Makes API Development Simple — August 20, 2018
Laravel and Lagan Web Services – SOAP API — August 17, 2018

Laravel and Lagan Web Services – SOAP API

SOAP is a dirty word to me. But I have a need to interact with our CRM system to import / extract data. My go to platform for most of my PHP work is Laravel. So I looked at interacting with Lagan CRM using SOAP calls from PHP.

I started off accessing the Lagan WSDL pages to see what the capabilities of the API are.

http://[laganserver:8080]/lagan/services/FL?WSDL
http://[laganserver:8080]/lagan/services/FLAuth?WSDL
http://[laganserver:8080]/lagan/schema/FLService.wsdl

Now I can see the self documenting API calls I can make. I just need to create the SOAP envelope to pass data to the service with the call I want to make.

Continue reading

Laravel API and Bootstrap Form Validation — August 13, 2018

Laravel API and Bootstrap Form Validation

This caused me some grief today. I spent the day adding validation rules into my Laravel resource controller and rather foolishly set HTML5 validation parameters on my Vue.js / Bootstrap 4 form component.

Why foolishly?

Well if you follow the Bootstrap 4 JavaScript function to call form.checkValidity() you’re actually calling the HTML5 built in function. Not a Bootstrap function as I originally thought.

When Laravel validation failed at the resource controller and it pushes back 422 (Unprocessable Entity) and a json error object:

{"message":"The given data was invalid.","errors":{"name":["The name field is required."]}}

I thought Bootstrap was seeing the Laravel validation errors and flagging up fields as not valid. So I could not understand why one of my fields didn’t show as invalid when according to Laravel it was!

What I was actually doing was HTML5 validation and ignoring my Laravel validation response all together. With the API it’s best NOT to try to use both HTML5 and Laravel validation. You’ll get a confusing UX that uses a mix of browser error messages/popups and Bootstrap CSS error handling.

Make sure you add novalidate to your form tag – this ensures HTML5 browser validation is prevented at the form level.

To resolve the Laravel validation part I just use the Laravel json error object and DON’T USE checkValidity(), my axios .catch(error) processes the Laravel errors by calling showErrors(error.response.data)

 this.axios.post('/api/v1/mycall/',
   this.data
 ).then(() => {
   // That worked out well, do something.
 }).catch(error => {
   this.showErrors(error.response.data)
 })

 showErrors: function (error) {
  Object.keys(error.errors).forEach((field) => {
    let input = document.getElementById(field)
    input.classList.add('is-invalid') // Bootstrap invalid form input
  })
 }

This iterates through the json errors and adds the class is-invalid to the fields that Laravel tells me are invalid. This triggers Bootstraps CSS to show the field with a red border and unhides the form-control subsequent/child div that has a class of invalid-feedback

References

https://getbootstrap.com/docs/4.1/components/forms/#validation

When using Vue.js and Laravels json response the actual usage is closer to the server-side examples:

https://getbootstrap.com/docs/4.1/components/forms/#server-side

Linting — August 6, 2018

Linting

No, this isn’t about taking the fluff from your belly button – but you’re close.

https://eslint.org/

Linting your written code is a method of ensuring that it meets consistent syntax and style guidelines. Eg. ensuring you indent function blocks by 4 spaces and not tabs, placing curly braces {} on new lines, having spaces following function names and parameters etc.

JavaScript, being a dynamic and loosely-typed language, is especially prone to developer error. Without the benefit of a compilation process, JavaScript code is typically executed in order to find syntax or other errors. Linting tools like ESLint allow developers to discover problems with their JavaScript code without executing it.

ESLint is a great way of ensuring my (ECMA)JavaScript coding style is consistent and correct. Using it within atom.io is a great way to keep my work tidy. Just add the ESLint package and we’re set to track and tidy my .js files.

But I want the same rules for my .vue files. I found this really handy: https://alligator.io/vuejs/vue-eslint-plugin/

Add the atom package linter-eslint then go to its settings button.

Find the option “List of scopes to run ESLint on…” and add onto it:

text.html.vue

So in my case it becomes:

source.js, source.jsx, source.js.jsx, source.babel, source.js-semantic, text.html.vue

 

Laravel Debug Bar —

Laravel Debug Bar

It’s a good job my job title doesn’t include development. Some things I find out seem a long time after I need then and would be useful in the world of development.

My latest discovery is the Laravel debug bar. https://github.com/barryvdh/laravel-debugbar

Using it means not so many dd() or dump() in my code to find out what Laravel sees. It even allows me to see the actual SQL queries being used.

Selection_073
Laravel Debug Bar

In many ways I wish I’d discovered this sooner.

Installation is very simple, just a composer require and then ensure your .env has the debug option enabled and/or debug bar enabled.

APP_DEBUG=true
DEBUGBAR_ENABLED=true

 

I Hate Internet Explorer — August 1, 2018

I Hate Internet Explorer

I just can’t seem to get it to die! Probably something to do with all those users out there spoiling my day and continuing to use it in Windows 7 – sadly in our corporate environment.

I’ve spent a few days with a problem showing “Syntax Error” in IE11 when my project runs just great in Edge, FireFox and Chrome.

After a lot of digging around in the components I’ve used I narrowed it down to one specific 3rd party component from npmjs. So I took a trawl through into the Github of the project and opened an issue. Turns out I’m not the only one seeing the problem. I guess everyone else is using more sensible browsers.

I got a great reply that pointed me to modifying my webpack config so it transpiled into IE11 compatible code. I’d already used polyfills like es6-promise and es6-object-assign and then babel-polyfill, but this obviously wasn’t enough.

The pointer was aimed at webpack. Now Laravel uses it’s own layer above webpack – Laravel-Mix, but with a bit more Googling I figured out how to add the necessary webpack config into mix to get it transpiling correctly.

Add the targets-webpack-plugin using yarn (or npm) as a “devDependency”

$ yarn add targets-webpack-plugin -D

In my webpack.mix.js file:

const TargetsPlugin = require('targets-webpack-plugin')

...

mix.webpackConfig({
  plugins: [
    new TargetsPlugin({
      browsers: ['last 2 versions', 'chrome >= 41', 'IE 11'],
    }),
  ]
})

Repackage my app with yarn run dev and IE11 is silent!

The internet is full of wonderfully helpful people. To those that post responses, write blogs or any kind of feed – I thank you all.

 

Axios and the X-CSRF-TOKEN —

Axios and the X-CSRF-TOKEN

When using Laravel it adds in some helpful headers to handle axios requests internally. But when it comes to sending requests externally you end up sending them the common headers added by Laravel and any plugins you may have added.

This typically includes the X-CSRF-TOKEN which your site uses to prevent Cross Site Request Forgery. But you don’t really want to send that out to external axios calls and in fact I’ve struggled as the sites I was using axios with returned a browser error because of it not being listed in their allowed headers:

SEC7123: Request header x-csrf-token was not present in the Access-Control-Headers-List.

SCRIPT7002: XMLHttpRequest: Network Error 0x8007005, Access is denied.

In order to resolve this you need to remove the headers from your axios call.

To do this I created a new instance of axios and returned that as my axios function.

let instance = this.$http.get(url, {
  transformRequest: function(data, headers) {
    delete headers.common['X-CSRF-TOKEN']
    delete headers.common['Authorization']
  }
})
return instance

I also added into here the removal of the Authorization header as that too should not go outside, and failed with the same message.

 

Yarn, npm and Git — July 31, 2018

Yarn, npm and Git

I’m kinda new to this hosting software externally. I’ve been happy using Gitlab for internal private projects, but recently I’ve been forking and reworking the work of others to include into my own.

So I thought I’d try publishing them back out to npmjs.com and github,com.

Publishing up to github is pretty straight forward. Using git from the command line to just add, commit and push is all the same, just now with an online repository rather than the internal Gitlab. In fact once the repository is added to the project I’m betting the Atom.io built in Git will handle the committing and pushing.

Recently I decided to have a look at yarn – it uses the npmjs repository just like npm. So far I’m liking it. It’s kinda pretty and I do like the caching.

I pretty much use yarn where ever I would have used npm. So instead of npm init I use yarn initnpm install I now use yarn add. Where I used npm run dev now it’s yarn run dev, and yarn run hot, etc.

Publishing

Now to push my packages up to npmjs. First you have to have an npmjs account, so sign up. Like Github, npmjs is only free for “public” packages. If you want “private”, you have to pay.

Then link yarn and npm up to your npmjs account using login.

$ yarn login
yarn login v1.7.0
question npm username: mynpmjsname
question npm email: me@mail.com 
Done in 32.16s.

Similarly for npm.

This saves an auth token into your .npmrc file so if you’ve supplied the password already you won’t need it to publish with. What I found after pushing up to git and publishing to npmjs was that I was doing things in the wrong order. So used to doing git commit and push, it’s second nature.

Before you git push to github, publish the package to npmjs. Do it this way because it will force a version increment which will do a git commit. Because it will have incremented the version in your package.json.

The name, version and description etc. in your package.json is what will be used by your project.

Because you are likely to want to publish what is probably a private project name (beginning with @) to a public project you’ll need to tell your publish command to make it public, or you’ll get a warning pretty much about about not having subscribed to publish private projects.

$ yarn publish --access=public

When you look at your projects in your npmjs.com profile you’ll see your fresh project ready for everyone to consume!

$ yarn publish
yarn publish v1.7.0
[1/4] Bumping version... 
info Current version: 1.8.1 
question New version: 1.8.2 
info New version: 1.8.2 
[2/4] Logging in... 
[3/4] Publishing... 
success Published. 
[4/4] Revoking token... 
info Not revoking login token, specified via config file. 
Done in 8.85s.

But that’s how easy it was to publish up to npmjs!

Now you’ve pushed to npmjs, you can do a git push to deliver the same project up to Github.com now with the new version.

References

https://yarnpkg.com/en/docs/creating-a-package