Security.jsx 9.98 KB
import { useState } from 'react'
import { Head, useForm } from '@inertiajs/react'
import Layout from '../Layout'
import SuccessMessage from '../../components/SuccessMessage'
import ErrorMessage from '../../components/ErrorMessage'

export default function SessionsSecurity({ auth, security_settings, flash }) {
  const { data, setData, patch, processing, errors } = useForm({
    require_two_factor: security_settings?.require_two_factor || false,
    session_timeout_minutes: security_settings?.session_timeout_minutes || 60,
    notify_on_new_login: security_settings?.notify_on_new_login || true,
    max_sessions: security_settings?.max_sessions || 5,
  })

  const handleSubmit = (e) => {
    e.preventDefault()
    patch('/sessions/security', {
      preserveScroll: true,
    })
  }

  return (
    <Layout user={auth}>
      <Head title="Session Security" />
      
      <div className="max-w-7xl mx-auto py-6 sm:px-6 lg:px-8">
        <div className="px-4 py-6 sm:px-0">
          <div className="bg-white shadow overflow-hidden sm:rounded-lg">
            <div className="px-4 py-5 sm:px-6">
              <h1 className="text-lg leading-6 font-medium text-gray-900">Session Security Settings</h1>
              <p className="mt-1 max-w-2xl text-sm text-gray-500">
                Manage your account security preferences.
              </p>
            </div>
            
            {flash?.success && (
              <div className="px-4 sm:px-6">
                <SuccessMessage message={flash.success} />
              </div>
            )}
            
            {flash?.error && (
              <div className="px-4 sm:px-6">
                <ErrorMessage message={flash.error} />
              </div>
            )}
            
            <div className="border-t border-gray-200 px-4 py-5 sm:p-6">
              <form onSubmit={handleSubmit} className="space-y-6">
                <div>
                  <div className="flex items-start">
                    <div className="flex items-center h-5">
                      <input
                        id="require_two_factor"
                        name="require_two_factor"
                        type="checkbox"
                        checked={data.require_two_factor}
                        onChange={(e) => setData('require_two_factor', e.target.checked)}
                        className="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded"
                      />
                    </div>
                    <div className="ml-3 text-sm">
                      <label htmlFor="require_two_factor" className="font-medium text-gray-700">
                        Require two-factor authentication
                      </label>
                      <p className="text-gray-500">
                        When enabled, you'll be required to provide a verification code in addition to your password when logging in.
                      </p>
                    </div>
                  </div>
                  {errors.require_two_factor && (
                    <p className="mt-2 text-sm text-red-600">{errors.require_two_factor}</p>
                  )}
                </div>
                
                <div>
                  <div className="flex items-start">
                    <div className="flex items-center h-5">
                      <input
                        id="notify_on_new_login"
                        name="notify_on_new_login"
                        type="checkbox"
                        checked={data.notify_on_new_login}
                        onChange={(e) => setData('notify_on_new_login', e.target.checked)}
                        className="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded"
                      />
                    </div>
                    <div className="ml-3 text-sm">
                      <label htmlFor="notify_on_new_login" className="font-medium text-gray-700">
                        Email notifications for new logins
                      </label>
                      <p className="text-gray-500">
                        Receive an email notification when a new device logs into your account.
                      </p>
                    </div>
                  </div>
                  {errors.notify_on_new_login && (
                    <p className="mt-2 text-sm text-red-600">{errors.notify_on_new_login}</p>
                  )}
                </div>
                
                <div>
                  <label htmlFor="session_timeout_minutes" className="block text-sm font-medium text-gray-700">
                    Session timeout (minutes)
                  </label>
                  <div className="mt-1">
                    <select
                      id="session_timeout_minutes"
                      name="session_timeout_minutes"
                      value={data.session_timeout_minutes}
                      onChange={(e) => setData('session_timeout_minutes', e.target.value)}
                      className="mt-1 block w-full pl-3 pr-10 py-2 text-base border-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-md"
                    >
                      <option value="15">15 minutes</option>
                      <option value="30">30 minutes</option>
                      <option value="60">1 hour</option>
                      <option value="120">2 hours</option>
                      <option value="240">4 hours</option>
                      <option value="480">8 hours</option>
                      <option value="1440">24 hours</option>
                    </select>
                  </div>
                  <p className="mt-2 text-sm text-gray-500">
                    Your session will automatically expire after this period of inactivity.
                  </p>
                  {errors.session_timeout_minutes && (
                    <p className="mt-2 text-sm text-red-600">{errors.session_timeout_minutes}</p>
                  )}
                </div>
                
                <div>
                  <label htmlFor="max_sessions" className="block text-sm font-medium text-gray-700">
                    Maximum active sessions
                  </label>
                  <div className="mt-1">
                    <select
                      id="max_sessions"
                      name="max_sessions"
                      value={data.max_sessions}
                      onChange={(e) => setData('max_sessions', e.target.value)}
                      className="mt-1 block w-full pl-3 pr-10 py-2 text-base border-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-md"
                    >
                      <option value="1">1 session</option>
                      <option value="2">2 sessions</option>
                      <option value="3">3 sessions</option>
                      <option value="5">5 sessions</option>
                      <option value="10">10 sessions</option>
                      <option value="0">Unlimited</option>
                    </select>
                  </div>
                  <p className="mt-2 text-sm text-gray-500">
                    Limit the number of devices that can be logged into your account simultaneously. When the limit is reached, the oldest session will be terminated.
                  </p>
                  {errors.max_sessions && (
                    <p className="mt-2 text-sm text-red-600">{errors.max_sessions}</p>
                  )}
                </div>
                
                <div className="flex justify-end">
                  <button
                    type="submit"
                    disabled={processing}
                    className="inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 disabled:opacity-50"
                  >
                    {processing ? 'Saving...' : 'Save Settings'}
                  </button>
                </div>
              </form>
            </div>
            
            <div className="border-t border-gray-200 px-4 py-5 sm:px-6 bg-gray-50">
              <h3 className="text-lg font-medium leading-6 text-gray-900">Security Actions</h3>
              <div className="mt-4 space-y-4">
                <div>
                  <button
                    type="button"
                    className="inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md shadow-sm text-white bg-red-600 hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500"
                    onClick={() => {
                      if (confirm('Are you sure you want to terminate all other sessions? This will log out all devices except your current one.')) {
                        window.location.href = '/sessions/terminate_all'
                      }
                    }}
                  >
                    Terminate All Other Sessions
                  </button>
                  <p className="mt-2 text-sm text-gray-500">
                    This will immediately log out all devices except your current one.
                  </p>
                </div>
                
                <div>
                  <button
                    type="button"
                    className="inline-flex items-center px-4 py-2 border border-gray-300 text-sm font-medium rounded-md shadow-sm text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
                    onClick={() => {
                      window.location.href = '/sessions'
                    }}
                  >
                    View Active Sessions
                  </button>
                  <p className="mt-2 text-sm text-gray-500">
                    See all devices currently logged into your account.
                  </p>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </Layout>
  )
}