Laravel – re-assign relationships in updates

Alternate title: Stop stuffing around with entity_id.

Working on a project with a representative – a user who looks after the company.

When changing the representative, I want to supply the whole representative to the update method – e.g. $customer->representative is an object with an id, name, etc. It’s just a pointer, but it means less double handling to send in the object.

I do not want to extract the ID from the object that the user supplied and pass that to the controller.


In the Company model, we need a ‘setRepresentativeAttribute’ method. This extracts the ID and puts it in the representative_id column.

    public function setRepresentativeAttribute($value)
    {
        $this->attributes['representative_id'] = $value['id'];
    }

Instead of making sure representative_id is fillable, we now need to make sure representative is fillable on the model.

protected $fillable = ['representative']; //not representative_id

It’s a simple pattern, but also one I’ve implemented the long way in the past.

Vue.js – mapGetters with Params

Using mapGetters with parameters isn’t well defined in the docs, and is a pattern I go to use pretty regularly.

I never find a good search result, so here goes:

1.Define the getter in the store. Take note that the naming convention will be [store namespace]/[getter name] later. Since this is in my users store, it’ll be users/usersForMember. Note the function accepts a parameter.

  usersForMember: (state) => (member) => {
    return state.users.data.filter(u => u.member_id === member.id)
  }

2.Connect the component side getter to the getter in the vuex store. I kept trying to mangle mapGetters to accept my params. This is the wrong approach – it just need to be directly wired up. Note the [namespace]/[getter name] convention from above, so vue can find the getter.

  
import { mapState, mapGetters } from 'vuex'

/* snip */

computed: {
    ...mapState({
      // other stuff
    }),
    ...mapGetters({
  // this is it.
      usersForMember: 'users/usersForMember'
    }),

Now, the piece I always miss! Write a method in the component to call the getter with the parameter.

  computed: {
    /* snip, from above */
// this is it:
    users () {
      return this.usersForMember({ id: this.user.member_id })
    }
  }

Over in the template, we can now output {{users}} and see the results of our handywork.

VueX Patterns: Updating in Array

When working on a type of entity, it’s common to post the new or updated entity to the server and then need to update it in the local vuex data store.

This is a simple pattern that propagates the changes to the UI displaying the list of entities.

1. Save the entity, from the UI.

 this.$store
          .dispatch('catalogs/create', {
            catalog: this.user
          })

2. POST the entity to the server in a vuex action, and pass the response to a mutation.
Note we also return the response data, in case the UI needs it for a flash message.

 async create (context, { user }) {
    const responseUser = await this.$axios.$post('users', user)
    context.commit('userFetched', responseUser.data)
    return responseUser
  },

3. Replace the object in array if it already exists. If it doesn’t exist, push it to the bottom of the array. Clone the array to trigger a UI update.

  userFetched (state, user) {
    const existsAtIndex = state.users.data.findIndex(u => u.id === user.id)

    if (existsAtIndex !== -1) {
      state.users.data[existsAtIndex] = user
    } else {
      state.users.data.push(user)
    }

    state.users.data = [...state.users.data]
  }

4. The UI which lists these users (UserRow below) will update itself with the new entry.

 computed: mapState({ users: state => state.users.users }),
<UserRow v-for="user in users.data" :key="user.id" :user="user" />

Solar in Bargo – numbers

We installed solar at our house in Bargo 2574 (a town in Wollondilly, NSW) in March 2020.

It cost approximately $5k for a 6.5kW system (feeding into a 5kW inverter). Half the panels face west, and half face north.

I’ve always been concerned that people who install solar need to convince the world that it was a good decision, and they often mask the real numbers involved. With that, here’s some real numbers.

A few interesting points, after a week of ownership.

A sunny day in Summer generates >30kW ($9 of electricity). The effective timespan is 8:30am (~1kW) until 6pm (~1kW). From 11am until 4pm the system generates consistently generates between 4-5kW. The highest I’ve seen is just slightly over 5kW, so I assume it maxes out there.

A gloomy day, raining from sunrise to sunset is generating ~5kW max for the day. ($1.50 of electricity)

Our usage (6 person household, 3 x split system air conditioners, tvs left on, 2x fridges, always using a dryer, and a pool) is 30-40kWh/day ($9-12 of electricity per day). This means on the sunny days we’re generating as much power as we’re using.

Unfortunately, the feed-in payment will be 10c/kW (where it costs ~30c/kW to consume) so we expect that even with perfect summer days we will still generate a bill*.

I’m not sure what our day/night consumption is like relative to the solar power generation window of 8:30-6pm, and obviously those goalposts will continue to move after summer. We’re expecting a 30-40% drop on our electricity bills and a 2 year repayment window on the $5k outlay.

*At the moment, our power meter (that is read manually every 3 months) cycles backwards when we are generating excess power. Wish we could leave it that way, it’s effectively 30c/kW feed-in payment too! I have a feeling the energy company won’t waste time fixing that.

I’ll follow this up when we receive our next power bill. The solar system was installed the day after our quarterly bill rolled over, so we should get a very realistic number on what we’ve saved.

Vue.js fragments

All manner of googling didn’t turn up a good result for this problem.

Sometimes, you need a wrapper component with logic attached that does not render to the UI.

For example, child components with a percentage of the parent can’t just have a div wrapped around them for conditional logic.

Another example (which I found a different, novel solution for) is using more than one child component in a root node. Only one renders, but a few are there and are excluded by logic.

React has a ‘fragment’ for this and afaik vue.js does not.

Using ‘vue-fragment’ adds a helpful fragment tag that is removed during render, but allows application of logic and generally acting as a ‘root’ component for multiple siblings.

below, we are using a ‘fragment’ tag to render or hide 2 items based on if the user is an admin. Trivially wrapping these in a div with logic breaks the layout.

                <b-navbar-nav>
                    <b-nav-item :to="'/'">
                        Dashboard
                    </b-nav-item>
                    <b-nav-item :to="'/something'">
                        Something
                    </b-nav-item>

                    <fragment v-if="user.role === 'Admin'">
                        <b-nav-item :to="'/item-1'">
                            Item 1
                        </b-nav-item>
                        <b-nav-item :to="'/item-2'">
                            Item 2
                        </b-nav-item>
                       
                    </fragment>
                </b-navbar-nav>

Install from yarn (or npm i vue-fragment)

yarn add vue-fragment

Add the fragment component

import { Plugin } from 'vue-fragment'
import Vue from 'vue'
Vue.use(Plugin)
<fragment>
  <div>Use the fragment! The fragment tag will be removed at render time.</div>
</fragment>

Nuxt.js Mixin – access global property in template

Adding a mixin in nuxt.js is just like adding a plugin. For my project, I needed a date format property set once but accessible in all my templates (named ‘moment_format’)

Step 1, In plugins/, create a plugin file (Mine is called ‘vue-format-global.js)

// plugins/vue-format-global.js
import Vue from 'vue'

var mixin = {
  data: function () {
    return {
      moment_format: 'DD/MM/YYYY HH:mm'
    }
  }
}

Vue.mixin(mixin)

Step 2, connect up the plugin in nuxt.config.js

  // in nuxt.config.js

  /*
  ** Plugins to load before mounting the App
  */
  plugins: [
    /* other plugins ... */
    '~/plugins/vue-format-global'
  ],

Step 3, restart the app and use freely in your templates.

// inside a template
<template>
effective since {{data.effective_date | moment(moment_format)}}
</template>

Nuxt.js and Vuex – dumping flash messages

Context:

  • A child component has received an error message, and needs to communicate it to the parent layout.
  • There’s no unhacky way to do that, so we should put it in the application store (vuex).
  • When the user navigates, the error is retained forever more.

It’s a problem seemingly without a clean answer.

Step 1: In the vuex store, create an errors array to hold the errors. Create two mutations: ‘set_errors’ and ‘clear_errors’.

// store/index.js
export const state = () => ({
  errors: []
})

export const mutations = {
  errors (state, errors) {
    state.errors = errors
  },
  clear_errors (state) {
    state.errors = []
  }
}

Step 2: In the component generating the error, put the errors in the vuex store.

// sign in has failed.
.catch(e => {
        let errors
        switch (e.response.status) {
          case 422:
            errors = this.translateErrors(e.response.data.errors)
            this.$store.commit('set_errors', errors)
            break
        }
      })

Step 3: In the ‘Errors’ component that lives in the layout, capture and display the errors. Confirm these two pieces are communicating.

// components/Errors.vue

<template>
    <div>
      {{errors.map(e => e)}}
    </div>
</template>

<script>
import { mapState } from 'vuex'
export default {
  computed: mapState(['errors'])
}
</script>

If that’s all working, it’s time to clear the message between navigation events.

Step 4: Create a ‘clearFlash’ middleware.

// middleware/clearFlash.js

export default function (context) {
  if (context.store.state.errors.length > 0) {
    context.store.commit('clear_errors')
  }
}

Step 5: Wire up the middleware in nuxt.config.js. Add the router and middleware keys if needed.

//nuxt.config.js

  router: {
    middleware: 'clearFlash'
  },

All done and working!

Dumping redux state on log out

When a user signs out of my mobile app and signs in as a different user, we need to make sure no application state can be carried over.

Adding a simple ‘LOGGED_OUT’ action that drops the application state is a straight forward solution. I’m keeping a few properties.

Here’s the normal reducers object that is exported.

var { combineReducers } = require('redux')

const reducers = combineReducers({
  attachments: require('./attachments'),
  user: require('./user'),
  //...etc
});

module.exports = reducers //or export default etc.

We can wrap the existing reducer with a single reducer that resets the state. Below, I’ve chosen to keep a few properties of my application state (out of about 20).

//existing reducers
const reducers = combineReducers({
  attachments: require('./attachments'),
  user: require('./user'),
  //...etc
});

//wrapped with the logged out action
const reducersWithLogoutDumpState = (state, action) => {
  if (action.type === 'LOGGED_OUT') {
    let newState = {}
    ['projects', 'device', 'user'].map(k => {
      newState[k] = state[k]
    })
    state = newState
  }
  return reducers(state, action)
}

module.exports = reducersWithLogoutDumpState

Here I’m creating a fresh state object (newState) and retaining the projects, device, and user properties from the old state.

Note that the export has changed to the new function name, so there’s no other changes throughout the application.

(An adaptation of the answer here: https://stackoverflow.com/questions/35622588/how-to-reset-the-state-of-a-redux-store.

Handling payments securely in React Native

I’m rebuilding an e-commerce mobile app side project (WooToApp) that requires payment for orders created.

The initial gateway is Paypal, but it’s an important part of the mobile app that there could be many more gateways, so the architecture needs to be re-usable and secure.

Basic architecture

Assumptions

We need to assume that the mobile app context is insecure. It’s easy to decompile a mobile app and extract keys, and it’s easy to copy HTTP requests to update an order as paid. Both of these are deal breakers.

We can assume the payment gateway and the app backend are secure.

With these assumptions, I made this quick architecture map to follow.

Quick explanation

It’s a relatively common pattern – the mobile app signals intention to pay to the backend.

The backend talks to the gateway, and returns the mobile app just enough information to pay (a redirect to a payment page)

The gateway then notifies the backend that payment has been authorised, which updates store and the mobile app.

Note above that the only components doing any sort of heavy lifting are our trusted components (app backend and payment gateway). We don’t trust any sensitive data from the mobile app or the ecommerce store.

Explicitly defining the architecture before starting work (and fine tuning along the way) means it’s easy to get into ‘thinking’ mode and define the secure boundaries and map it out.

In the next sitting when it’s time to write the implementation, the architecture and security considerations are both fresh in your mind AND documented. It’s a lot easier than architecting and reasoning about security along the way.

Payment Handling

I won’t dive into the server side payment handling here. There’s nothing exciting there, it’s just nothing innovative. A nodejs script (the app backend) captures the payment request from the mobile app and creates a payment request that paypal understands. Paypal gives the backend a redirect URL.

In the mobile app, we should a secure frame for the customer to make payment to the gateway. Paypal redirects the user to a URL that notifies the backend that payment was received, which redirects the user to the app thankyou page.

The mobile app has zero knowledge of paypal libraries and integrations. There’s no surface area for the mobile app to be vulnerable. Secret keys are never safe in a mobile application.

Payment UI

This is a pretty important one. The regular webview in React Native is susceptible to manipulation and as far as I know should not be used for any type of third party secure communication in React Native. For example, an app developer is able to inject a JS keylogger. It’s flawed by design.

iOS and Android both make a secure browser context available that is not susceptible to manipulation, which has been abstracted into a useful library here.

Once payment has been made, the gateway success URL redirects back to a deep link for the mobile app (think myapp://order-paid/505). React-Navigation deep linking works with simple code changes to handle this.

There’s a small issue to work around – the popped out web browser context successfully causes the deep link to fire and navigate to the correct page in the mobile app, but you can’t see it because the web browser context stays open on the top.

The Order Paid page will always be the result of a deep linked action, so we can just hide the browser when the page initiates.