QPANC - Parte 17 - Quasar - Registro
Tags: quasar, postgres, aspnetcore, docker
Published: 2020-04-19 23:38:52

> **QPANC** são as iniciais de **Q**uasar **P**ostgreSQL **A**SP **N**ET **C**ore.

  * [Source](https://github.com/TobyMosque/qpanc)
  * [Introdução](https://dev.to/quasar-pt-br/arquiteturando-uma-aplicacao-com-quasar-postgresql-asp-net-core-e-docker-introducao-o7o)
  * [Parte I - ASP.NET - Inicializando os Projetos](https://dev.to/quasar-pt-br/qpanc-parte-1-asp-net-inicializando-os-projetos-lkm)
  * [Parte 2 - PostgreSQL](https://dev.to/quasar-pt-br/qpanc-parte-2-postgresql-51pb)
  * [Parte 3 - ASP.NET - Registrando Serviços e Lendo Variáveis de Ambiente](https://dev.to/quasar-pt-br/qpanc-parte-3-asp-net-registrando-servicos-e-lendo-variaveis-de-ambiente-3do2)
  * [Parte 4 - ASP.NET - Entity Framework e ASP.NET Core Identity](https://dev.to/quasar-pt-br/qpanc-parte-4-asp-net-entity-framework-e-asp-net-core-identity-40f9)
  * [Parte 5 - ASP.NET - Documentação Interativa com Swagger](https://dev.to/quasar-pt-br/qpanc-parte-5-asp-net-documentacao-interativa-com-swagger-4n0o)
  * [Parte 6 - ASP.NET - Regionalização](https://dev.to/quasar-pt-br/qpanc-parte-6-asp-net-regionalizacao-13p5)
  * [Parte 7 - ASP.NET - Autenticação e Autorização](https://dev.to/quasar-pt-br/qpanc-parte-7-asp-net-autenticacao-e-autorizacao-bpd)
  * [Parte 8 - ASP.NET - CORS](https://dev.to/quasar-pt-br/qpanc-parte-8-asp-net-cors-52dn)
  * [Parte 9 - Quasar - Criação e Configuração do Projeto](https://dev.to/quasar-pt-br/qpanc-parte-9-quasar-criacao-e-configuracao-do-projeto-5hbi)
  * [Parte 10 - Quasar - Configurações e Customizações](https://dev.to/quasar-pt-br/qpanc-parte-10-quasar-configuracoes-e-customizacoes-2i86)
  * [Parte 11 - Quasar - Componentes - Diferença entre SPA e SSR](https://dev.to/quasar-pt-br/qpanc-parte-11-quasar-componentes-diferenca-entre-spa-e-ssr-1a3c)
  * [Parte 12 - Quasar - Serviços](https://dev.to/quasar-pt-br/qpanc-parte-12-quasar-servicos-4e61)
  * [Parte 13 - Quasar - Regionalização e Stores](https://dev.to/quasar-pt-br/qpanc-parte-13-quasar-regionalizacao-e-stores-1kep)
  * [Parte 14 - Quasar - Consumindo a API](https://dev.to/quasar-pt-br/qpanc-parte-14-quasar-consumindo-a-api-fn6)
  * [Parte 15 - Quasar - Login](https://dev.to/quasar-pt-br/qpanc-parte-15-quasar-login-jc6)
  * [Parte 16 - Quasar - Áreas Protegidas](https://dev.to/quasar-pt-br/qpanc-parte-16-quasar-areas-protegidas-3jkn)
  * [Parte 17 - Quasar - Registro](https://dev.to/quasar-pt-br/qpanc-parte-17-quasar-registro-3b8c)
  * [Parte 18 - Docker - Maquina Virtual Linux](https://dev.to/quasar-pt-br/qpanc-parte-18-docker-maquina-virtual-linux-g5c)
  * [Parte 19 - Docker - Registro e Build](https://dev.to/quasar-pt-br/qpanc-parte-19-docker-registro-e-build-31i4)
  * [Parte 20 - Docker - Traefik e Publicação](https://dev.to/quasar-pt-br/qpanc-parte-20-docker-traefik-e-publicacao-3g3d)
  * [Demo Online](https://qpanc.tobiasmesquita.dev)

##35 Registrar Usuário.

Antes de criamos o componente de registro, precisamos adicionar duas novas regras de validação no `validations.js`

**QPANC.App/src/services/validations.js**
```js
validations.compare = ({ self, field }) => {
  return function required (val) {
    var other = self.validationArgs[field].compare
    return val === self[other] || self.$t('validations.compare', {
      field: self.$t(`fields.${field}`),
      other: self.$t(`fields.${other}`)
    })
  }
}

validations.strength = ({ self, field }) => {
  return function required (val) {
    const property = self.validationArgs[field].strength
    const strength = self[property]
    return strength < 0.6 || self.$t('validations.strength', {
      field: self.$t(`fields.${field}`)
    })
  }
}
```

A regra `compare` serve para comprar o valor de dois campos, o campo `other` é definido no `validationArgs.compare`.

A regra `strength` testa a força de uma senha, no caso, este valor varia de 0 à 1, por hora, iremos definir um valor de 0.6 como aceitável, o `validationArgs.strength` possui o nome da propriedade computada que realiza o calculo.

Agora, precisamos instalar o pacote `zxcvbn`, pois iremos utiliza-lo para validar a força da senha:

```
yarn add zxcvbn
```

Então, podemos criar a nossa pagina de registro

**QPANC.App/src/pages/home/store.js**
```js
import { factory } from '@toby.mosque/utils'
import { Dialog } from 'quasar'

class RegisterPageModel {
  constructor ({
    userName = '',
    confirmUserName = '',
    firstName = '',
    lastName = '',
    password = '',
    confirmPassword = ''
  } = {}) {
    this.userName = userName
    this.confirmUserName = confirmUserName
    this.firstName = firstName
    this.lastName = lastName
    this.password = password
    this.confirmPassword = confirmPassword
  }
}

const options = {
  model: RegisterPageModel
}

export default factory.store({
  options,
  actions: {
    async initialize ({ state }, { route, next }) {
    },
    async register ({ state }) {
      await this.$axios.post('/Auth/Register', state)
      this.$router.push('/login')
      Dialog.create({
        color: 'positive',
        message: this.$t('register.success')
      })
    }
  }
})

export { options, RegisterPageModel }
```

Na store não há nada de novo.

**QPANC.App/src/pages/home/index.js**
```js
import validations from 'services/validations'
import { factory } from '@toby.mosque/utils'
import store, { options } from './store'
import zxcvbn from 'zxcvbn'

const moduleName = 'page-register'
export default factory.page({
  name: 'RegisterPage',
  options,
  moduleName,
  storeModule: store,
  created () {
    if (process.env.CLIENT) {
      this.$root.$on('unprocessable', this.unprocessable)
    }
  },
  destroy () {
    if (process.env.CLIENT) {
      this.$root.$off('unprocessable', this.unprocessable)
    }
  },
  data () {
    const self = this
    const validation = validations(self, {
      userName: ['required', 'email', 'server'],
      confirmUserName: ['required', 'compare', 'email'],
      firstName: ['required'],
      lastName: ['required'],
      password: ['required', 'strength', 'server'],
      confirmPassword: ['required', 'compare']
    })
    return {
      validation,
      validationArgs: {
        userName: {
          server: true
        },
        confirmUserName: {
          compare: 'userName'
        },
        password: {
          server: true
        },
        confirmPassword: {
          compare: 'password'
        }
      }
    }
  },
  computed: {
    strength () {
      if (!this.password) {
        return 0
      }
      const strength = zxcvbn(this.password).score + 1
      return strength / 5
    },
    strColor () {
      switch (this.strength) {
        case 1: return 'blue'
        case 0.8: return 'green'
        case 0.6: return 'yellow'
        case 0.4: return 'orange'
        case 0.2: return 'red'
        default: return 'grey'
      }
    }
  },
  methods: {
    unprocessable (errors) {
      switch (true) {
        case !!errors.UserName: this.validationArgs.userName.server = errors.UserName[0]; break
        case !!errors.Password: this.validationArgs.password.server = errors.Password[0]; break
      }
      this.$refs.form.validate()
    },
    async register () {
      this.validation.resetServer()
      const isValid = await this.$refs.form.validate()
      if (isValid) {
        this.$store.dispatch(`${moduleName}/register`)
      }
    }
  }
})
```

No script do componente, você pode observar o `data`, onde agora temos as regras `compare` e `strength`, e no `confirmUserName` estamos a definir as depedencias para estas validações.

No `computed`, temos o `strength` e `strColor`, que é utilizado para mensurar a força do `password`.

> Lembrando que a regra usada pelo `zxcvbn` não é a mesma regra que é utilizado no servidor, por tanto, o `back` pode vir a reclamar da senha, mesmo que o `front `o aprove, então o ideal é que use o `zxcvbn` no backend, ou replique os requerimentos do `back` no `front`

**QPANC.App/src/pages/home/index.sass**
```sass
#page-register
```
**QPANC.App/src/pages/home/index.vue**
```html
<template>
  <div id="page-register">
    <h5 class="q-my-md">{{$t('register.title')}}</h5>
    <q-separator></q-separator>
    <q-form ref="form" class="row q-col-gutter-sm">
      <div class="col col-12">
        <q-input v-model="userName" :label="$t('fields.userName')" :rules="validation.userName" @blur="validationArgs.userName.server = true"></q-input>
      </div>
      <div class="col col-12">
        <q-input v-model="confirmUserName" :label="$t('fields.confirmUserName')" :rules="validation.confirmUserName"></q-input>
      </div>
      <div class="col col-12">
        <q-input v-model="firstName" :label="$t('fields.firstName')" :rules="validation.firstName"></q-input>
      </div>
      <div class="col col-12">
        <q-input v-model="lastName" :label="$t('fields.lastName')" :rules="validation.lastName"></q-input>
      </div>
      <div class="col col-12">
        <q-input type="password" v-model="password" :label="$t('fields.password')" :rules="validation.password" @blur="validationArgs.password.server = true"></q-input>
        <q-linear-progress size="10px" stripe :value="strength" :color="strColor" ></q-linear-progress>
      </div>
      <div class="col col-12">
        <q-input type="password" v-model="confirmPassword" :label="$t('fields.confirmPassword')" :rules="validation.confirmPassword"></q-input>
      </div>
      <div class="col col-5">
        <q-btn class="full-width" color="secondary" :label="$t('actions.backLogin')" to="/login"></q-btn>
      </div>
      <div class="col col-7">
        <q-btn class="full-width" color="positive" :label="$t('actions.register')" @click="register"></q-btn>
      </div>
    </q-form>
  </div>
</template>

<script src="./index.js"></script>
<style src="./index.sass" lang="sass"></style>
```

A unica novidade aqui, é a presença do `QLinearProgress`.

E agora, um vídeo com o processo de registro e login

{% vimeo 409086444 %}