Skip to content

Instantly share code, notes, and snippets.

@Aslam97
Last active October 11, 2021 13:54
Show Gist options
  • Save Aslam97/4c320dac0c50f3bbfd64164ad8fdd61a to your computer and use it in GitHub Desktop.
Save Aslam97/4c320dac0c50f3bbfd64164ad8fdd61a to your computer and use it in GitHub Desktop.
Laravel change user password

Laravel change user password

Create Custom Validation Rules

  • Create CheckPassword rules

php artisan make:rule CheckPassword

use Illuminate\Contracts\Validation\Rule;
use Hash;
use Auth;
...

public function passes($attribute, $value)
{
    return Hash::check($value, Auth::user()->password);
}

public function message()
{
    return trans('validation.check_password');
}
  • Create ComparePassword rules

php artisan make:rule ComparePassword

use Illuminate\Contracts\Validation\Rule;
...

public $current_password;

public function __construct($current_password)
{
    $this->current_password = $current_password;
}
    
public function passes($attribute, $value)
{
    return strcmp($this->current_password, $value) == 0 ? false : true;
}

public function message()
{
    return trans('validation.compare_password');
}

Create Form Requests

php artisan make:request UserChangePassword

use Illuminate\Foundation\Http\FormRequest;
use App\Rules\CheckPassword;
use App\Rules\ComparePassword;
...

public function authorize()
{
    return true;
}

public function rules()
{
    return [
        'current_password' => ['required', 'string', new CheckPassword],
        'new_password' => ['required', 'string', 'min:8', new ComparePassword($this->current_password)]
    ];
}

routes/web.php

Route::post('/password/change', 'Controller@changePassword');

Controller

use App\Http\Requests\UserChangePassword;
...

public function changePassword(UserChangePassword $request)
{
    auth()->user()->update(['password' => bcrypt($request->new_password)]);
    return response()->json(['message' => trans('validation.change_password')]);
}

Translations

  • lang/validation.php
'check_password' => 'Your current password does not match the password you provided.',
'compare_password' => 'The new password cannot be the same as your current password. Please choose a different password.',
'change_password' => 'Password change successfully.',
@dricislam
Copy link

Hello , do u have the view ? thanks

@Aslam97
Copy link
Author

Aslam97 commented Sep 12, 2021

Hello , do u have the view ? thanks

@dricislam There is but with vue or you can take a look live example famicon.herokuapp.com email: [email protected] pass: adminadmin. idk if it still working or not

ChangePassword.js

<script>
export default {
  data: () => ({
    loading: false,
    current_password: '',
    new_password: '',
  }),

  methods: {
    onSubmit() {
      this.loading = true;
      this.$store
        .dispatch('user/changePassword', this.$data)
        .then(response => {
          this.loading = false;
          this.current_password = this.new_password = '';

          this.$toast({
            position: 'bottom',
            message: response.message,
          });

          this.$nextTick(() => {
            this.$refs.form.reset();
          });
        })
        .catch(({ data }) => {
          const { errors } = data;
          this.loading = false;
          this.$refs.form.setErrors(errors);
        });
    },
  },
};
</script>

<template>
  <ChildLayout
    :navigation="false"
    :header-title-uppercase="false"
    :header-name="$t('account.user_settings.change_password.title')"
  >
    <template #leftHeader>
      <RouterLink
        class="ArrowBack"
        :to="{ name: 'account' }"
        aria-label="back button"
      >
        <FmSvg icon="arrow_back" />
      </RouterLink>
    </template>

    <div class="default-layout-container">
      <ValidationObserver
        v-slot="{ invalid }"
        ref="form"
        tag="form"
        @submit.prevent="onSubmit"
      >
        <FamiconInput
          v-model="current_password"
          :name="$t('account.user_settings.change_password.current_password')"
          type="password"
          :label="true"
          rules="required"
          vid="current_password"
        />

        <FamiconInput
          v-model="new_password"
          :name="$t('account.user_settings.change_password.new_password')"
          type="password"
          :label="true"
          rules="required|min:8"
          vid="new_password"
        />

        <div class="card-footer text-right px-0 border-0">
          <div class="flex">
            <button
              type="submit"
              class="fm-btn fm-btn-green fm-btn-block fm-btn-normal"
              :disabled="invalid"
            >
              <FamiconSpinner v-if="loading" />
              <span v-else>
                {{ $t('account.user_settings.change_password.submit') }}
              </span>
            </button>
          </div>
        </div>
      </ValidationObserver>
    </div>
  </ChildLayout>
</template>

Vuex user.js

import axios from 'axios';

export const state = () => ({
  me: '',
});

export const mutations = {
  setMe(state, payload) {
    state.me = payload;
  },
};

export const actions = {
  me({ commit }) {
    return new Promise((resolve, reject) => {
      axios
        .get('/v2/me')
        .then(({ data }) => {
          resolve(data);
          commit('setMe', data);
        })
        .catch(({ response }) => reject(response));
    });
  },

  changePassword(_, payload) {
    return new Promise((resolve, reject) => {
      axios
        .post('/v2/account/password/change', payload)
        .then(({ data }) => resolve(data))
        .catch(({ response }) => reject(response));
    });
  },
};

FamiconInput.vue

<script>
import { FamiconForm } from '@/mixins';

export default {
  name: 'FamiconInput',
  mixins: [FamiconForm],
};
</script>

<template>
  <ValidationProvider
    v-slot="{ errors }"
    tag="div"
    :class="formGroupClass"
    :rules="rules"
    :name="name"
    :vid="vid"
  >
    <label
      v-if="label"
      :for="name"
      :class="formLabelClass"
    >
      {{ name }}
      <span
        v-if="isRequired"
        class="form-required"
      >*</span>
    </label>

    <input
      :id="name"
      v-model="currentValue"
      :type="type"
      :class="[
        formControlClass,
        { 'invalid-border': invalidBorder, 'is-invalid': errors[0] },
      ]"
      :placeholder="placeholder"
      :autocomplete="autocomplete"
      @input="handleInput"
    >
    <span class="invalid-feedback">{{ errors[0] }}</span>

    <small class="text-sm text-muted block mt-2">
      <slot name="form-help" />
    </small>
  </ValidationProvider>
</template>

Mixin.js

export const FamiconForm = {
  computed: {
    isRequired() {
      if (this.rules.includes('required')) return true;
      return false;
    },
  },

  props: {
    value: {
      type: [String, Number],
      default: '',
    },

    rules: {
      type: [String, Object],
      default: '',
    },

    name: {
      type: String,
      default: '',
    },

    placeholder: {
      type: String,
      default: '',
    },

    vid: {
      type: String,
      default: undefined,
    },

    type: {
      type: String,
      default: 'text',
    },

    label: {
      type: Boolean,
      default: false,
    },

    autocomplete: {
      type: String,
      default: '',
    },

    formGroupClass: {
      type: String,
      default: 'form-group',
    },

    formControlClass: {
      type: String,
      default: 'form-control form-control-normal',
    },

    formLabelClass: {
      type: String,
      default: 'form-label',
    },

    invalidBorder: {
      type: Boolean,
      default: true,
    },
  },

  data: () => ({
    currentValue: '',
  }),

  watch: {
    value: {
      handler(after) {
        this.currentValue = after;
      },
      immediate: true,
    },
  },

  methods: {
    handleInput() {
      this.$emit('input', this.currentValue);
    },
  },
};

@dricislam
Copy link

Thank you so much!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment