kaze 0.7.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -0
  3. data/lib/kaze/commands/install_command.rb +3 -1
  4. data/lib/kaze/commands/installs_hotwire_stack.rb +2 -2
  5. data/lib/kaze/commands/installs_inertia_stacks.rb +7 -7
  6. data/lib/kaze/version.rb +1 -1
  7. data/stubs/default/app/forms/auth/login_form.rb +2 -2
  8. data/stubs/default/app/forms/auth/new_password_form.rb +2 -2
  9. data/stubs/default/app/forms/auth/send_password_reset_link_form.rb +2 -4
  10. data/stubs/default/app/mailers/application_mailer.rb +1 -1
  11. data/stubs/default/app/mailers/user_mailer.rb +16 -1
  12. data/stubs/default/app/models/concerns/can_reset_password.rb +1 -1
  13. data/stubs/default/app/models/concerns/must_verify_email.rb +15 -0
  14. data/stubs/default/app/models/session_guard.rb +157 -0
  15. data/stubs/default/app/models/user.rb +1 -0
  16. data/stubs/default/app/views/user_mailer/reset_password.html.erb +2 -2
  17. data/stubs/default/app/views/user_mailer/verify_email.html.erb +33 -0
  18. data/stubs/default/config/routes.rb +4 -0
  19. data/stubs/default/db/migrate/20240101000000_create_users.rb +2 -0
  20. data/stubs/default/test/factories/users.rb +5 -0
  21. data/stubs/default/test/integration/auth/authentication_test.rb +4 -6
  22. data/stubs/default/test/integration/auth/email_verification_test.rb +40 -0
  23. data/stubs/default/test/integration/auth/password_reset_test.rb +3 -3
  24. data/stubs/default/test/integration/password_update_test.rb +2 -2
  25. data/stubs/default/test/integration/profile_test.rb +4 -4
  26. data/stubs/default/test/test_helper.rb +1 -1
  27. data/stubs/hotwire/app/components/application_logo_component.rb +2 -5
  28. data/stubs/hotwire/app/components/modal_component.rb +5 -5
  29. data/stubs/hotwire/app/controllers/auth/authenticated_session_controller.rb +3 -2
  30. data/stubs/hotwire/app/controllers/auth/email_verification_notification_controller.rb +21 -0
  31. data/stubs/hotwire/app/controllers/auth/new_password_controller.rb +2 -2
  32. data/stubs/hotwire/app/controllers/auth/password_reset_link_controller.rb +1 -1
  33. data/stubs/hotwire/app/controllers/auth/registered_user_controller.rb +6 -2
  34. data/stubs/hotwire/app/controllers/auth/verified_email_controller.rb +23 -0
  35. data/stubs/hotwire/app/controllers/concerns/authenticate.rb +10 -0
  36. data/stubs/hotwire/app/controllers/concerns/set_current_auth.rb +1 -1
  37. data/stubs/hotwire/app/controllers/concerns/validate_signature.rb +17 -0
  38. data/stubs/hotwire/app/controllers/password_controller.rb +1 -1
  39. data/stubs/hotwire/app/controllers/profile_controller.rb +2 -2
  40. data/stubs/hotwire/app/views/auth/verify_email.html.erb +23 -0
  41. data/stubs/hotwire/app/views/layouts/_navigation.html.erb +1 -1
  42. data/stubs/hotwire/app/views/layouts/guest.html.erb +1 -1
  43. data/stubs/hotwire/app/views/profile/partials/_delete_user_form.html.erb +1 -1
  44. data/stubs/inertia-common/app/controllers/auth/authenticated_session_controller.rb +3 -3
  45. data/stubs/inertia-common/app/controllers/auth/email_verification_notification_controller.rb +21 -0
  46. data/stubs/inertia-common/app/controllers/auth/new_password_controller.rb +2 -3
  47. data/stubs/inertia-common/app/controllers/auth/password_reset_link_controller.rb +3 -3
  48. data/stubs/inertia-common/app/controllers/auth/registered_user_controller.rb +6 -2
  49. data/stubs/inertia-common/app/controllers/auth/verified_email_controller.rb +23 -0
  50. data/stubs/inertia-common/app/controllers/concerns/authenticate.rb +10 -0
  51. data/stubs/inertia-common/app/controllers/concerns/set_current_auth.rb +1 -1
  52. data/stubs/inertia-common/app/controllers/concerns/validate_signature.rb +17 -0
  53. data/stubs/inertia-common/app/controllers/password_controller.rb +1 -1
  54. data/stubs/inertia-common/app/controllers/profile_controller.rb +2 -2
  55. data/stubs/inertia-common/test/integration/password_update_test.rb +2 -2
  56. data/stubs/inertia-common/test/integration/profile_test.rb +4 -4
  57. data/stubs/inertia-react-ts/app/javascript/Components/ApplicationLogo.tsx +2 -9
  58. data/stubs/inertia-react-ts/app/javascript/Components/Checkbox.tsx +1 -4
  59. data/stubs/inertia-react-ts/app/javascript/Components/DangerButton.tsx +3 -5
  60. data/stubs/inertia-react-ts/app/javascript/Components/Dropdown.tsx +4 -25
  61. data/stubs/inertia-react-ts/app/javascript/Components/InputError.tsx +1 -4
  62. data/stubs/inertia-react-ts/app/javascript/Components/InputLabel.tsx +1 -4
  63. data/stubs/inertia-react-ts/app/javascript/Components/NavLink.tsx +3 -5
  64. data/stubs/inertia-react-ts/app/javascript/Components/PrimaryButton.tsx +3 -5
  65. data/stubs/inertia-react-ts/app/javascript/Components/SecondaryButton.tsx +3 -5
  66. data/stubs/inertia-react-ts/app/javascript/Components/TextInput.tsx +1 -7
  67. data/stubs/inertia-react-ts/app/javascript/Layouts/AuthenticatedLayout.tsx +15 -53
  68. data/stubs/inertia-react-ts/app/javascript/Layouts/GuestLayout.tsx +1 -1
  69. data/stubs/inertia-react-ts/app/javascript/Pages/Auth/ForgotPassword.tsx +3 -6
  70. data/stubs/inertia-react-ts/app/javascript/Pages/Auth/Login.tsx +9 -23
  71. data/stubs/inertia-react-ts/app/javascript/Pages/Auth/Register.tsx +1 -4
  72. data/stubs/inertia-react-ts/app/javascript/Pages/Auth/ResetPassword.tsx +1 -4
  73. data/stubs/inertia-react-ts/app/javascript/Pages/Auth/VerifyEmail.tsx +47 -0
  74. data/stubs/inertia-react-ts/app/javascript/Pages/Dashboard.tsx +2 -8
  75. data/stubs/inertia-react-ts/app/javascript/Pages/Profile/Edit.tsx +1 -5
  76. data/stubs/inertia-react-ts/app/javascript/Pages/Profile/Partials/DeleteUserForm.tsx +7 -19
  77. data/stubs/inertia-react-ts/app/javascript/Pages/Profile/Partials/UpdatePasswordForm.tsx +7 -15
  78. data/stubs/inertia-react-ts/app/javascript/Pages/Profile/Partials/UpdateProfileInformationForm.tsx +7 -16
  79. data/stubs/inertia-react-ts/app/javascript/Pages/Welcome.tsx +1 -2
  80. data/stubs/inertia-react-ts/app/javascript/entrypoints/application.tsx +1 -5
  81. data/stubs/inertia-react-ts/config/tailwind.config.js +1 -6
  82. data/stubs/inertia-vue-ts/app/javascript/Components/ApplicationLogo.vue +4 -9
  83. data/stubs/inertia-vue-ts/app/javascript/Components/Dropdown.vue +1 -4
  84. data/stubs/inertia-vue-ts/app/javascript/Components/Modal.vue +3 -13
  85. data/stubs/inertia-vue-ts/app/javascript/Layouts/AuthenticatedLayout.vue +10 -45
  86. data/stubs/inertia-vue-ts/app/javascript/Layouts/GuestLayout.vue +3 -7
  87. data/stubs/inertia-vue-ts/app/javascript/Pages/Auth/ForgotPassword.vue +4 -11
  88. data/stubs/inertia-vue-ts/app/javascript/Pages/Auth/Login.vue +2 -10
  89. data/stubs/inertia-vue-ts/app/javascript/Pages/Auth/Register.vue +1 -5
  90. data/stubs/inertia-vue-ts/app/javascript/Pages/Auth/ResetPassword.vue +1 -4
  91. data/stubs/inertia-vue-ts/app/javascript/Pages/Auth/VerifyEmail.vue +50 -0
  92. data/stubs/inertia-vue-ts/app/javascript/Pages/Dashboard.vue +3 -11
  93. data/stubs/inertia-vue-ts/app/javascript/Pages/Profile/Edit.vue +2 -10
  94. data/stubs/inertia-vue-ts/app/javascript/Pages/Profile/Partials/DeleteUserForm.vue +5 -9
  95. data/stubs/inertia-vue-ts/app/javascript/Pages/Profile/Partials/UpdatePasswordForm.vue +2 -9
  96. data/stubs/inertia-vue-ts/app/javascript/Pages/Profile/Partials/UpdateProfileInformationForm.vue +3 -13
  97. data/stubs/inertia-vue-ts/app/javascript/Pages/Welcome.vue +2 -5
  98. data/stubs/inertia-vue-ts/config/tailwind.config.js +1 -6
  99. metadata +15 -4
  100. data/MIT-LICENSE +0 -20
  101. data/stubs/default/app/models/auth.rb +0 -57
@@ -16,9 +16,7 @@ const { pathname = '' } = typeof window !== 'undefined' ? window.location : {}
16
16
  <template>
17
17
  <div>
18
18
  <div class="min-h-screen bg-gray-100 dark:bg-gray-900">
19
- <nav
20
- class="bg-white dark:bg-gray-800 border-b border-gray-100 dark:border-gray-700"
21
- >
19
+ <nav class="bg-white dark:bg-gray-800 border-b border-gray-100 dark:border-gray-700">
22
20
  <!-- Primary Navigation Menu -->
23
21
  <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
24
22
  <div class="flex justify-between h-16">
@@ -26,20 +24,13 @@ const { pathname = '' } = typeof window !== 'undefined' ? window.location : {}
26
24
  <!-- Logo -->
27
25
  <div class="shrink-0 flex items-center">
28
26
  <Link href="/">
29
- <ApplicationLogo
30
- class="block h-9 w-auto fill-current text-gray-800 dark:text-gray-200"
31
- />
27
+ <ApplicationLogo class="block h-9 w-auto fill-current text-red-800 dark:text-red-200" />
32
28
  </Link>
33
29
  </div>
34
30
 
35
31
  <!-- Navigation Links -->
36
32
  <div class="hidden space-x-8 sm:-my-px sm:ms-10 sm:flex">
37
- <NavLink
38
- :href="dashboard_path()"
39
- :active="pathname.match(/dashboard/) != null"
40
- >
41
- Dashboard
42
- </NavLink>
33
+ <NavLink :href="dashboard_path()" :active="pathname.match(/dashboard/) != null"> Dashboard </NavLink>
43
34
  </div>
44
35
  </div>
45
36
 
@@ -72,16 +63,8 @@ const { pathname = '' } = typeof window !== 'undefined' ? window.location : {}
72
63
  </template>
73
64
 
74
65
  <template #content>
75
- <DropdownLink :href="profile_edit_path()">
76
- Profile
77
- </DropdownLink>
78
- <DropdownLink
79
- :href="logout_path()"
80
- method="post"
81
- as="button"
82
- >
83
- Log Out
84
- </DropdownLink>
66
+ <DropdownLink :href="profile_edit_path()"> Profile </DropdownLink>
67
+ <DropdownLink :href="logout_path()" method="post" as="button"> Log Out </DropdownLink>
85
68
  </template>
86
69
  </Dropdown>
87
70
  </div>
@@ -93,12 +76,7 @@ const { pathname = '' } = typeof window !== 'undefined' ? window.location : {}
93
76
  @click="showingNavigationDropdown = !showingNavigationDropdown"
94
77
  class="inline-flex items-center justify-center p-2 rounded-md text-gray-400 dark:text-gray-500 hover:text-gray-500 dark:hover:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-900 focus:outline-none focus:bg-gray-100 dark:focus:bg-gray-900 focus:text-gray-500 dark:focus:text-gray-400 transition duration-150 ease-in-out"
95
78
  >
96
- <svg
97
- class="h-6 w-6"
98
- stroke="currentColor"
99
- fill="none"
100
- viewBox="0 0 24 24"
101
- >
79
+ <svg class="h-6 w-6" stroke="currentColor" fill="none" viewBox="0 0 24 24">
102
80
  <path
103
81
  :class="{
104
82
  hidden: showingNavigationDropdown,
@@ -134,10 +112,7 @@ const { pathname = '' } = typeof window !== 'undefined' ? window.location : {}
134
112
  class="sm:hidden"
135
113
  >
136
114
  <div class="pt-2 pb-3 space-y-1">
137
- <ResponsiveNavLink
138
- :href="dashboard_path()"
139
- :active="pathname.match(/dashboard/) != null"
140
- >
115
+ <ResponsiveNavLink :href="dashboard_path()" :active="pathname.match(/dashboard/) != null">
141
116
  Dashboard
142
117
  </ResponsiveNavLink>
143
118
  </div>
@@ -145,9 +120,7 @@ const { pathname = '' } = typeof window !== 'undefined' ? window.location : {}
145
120
  <!-- Responsive Settings Options -->
146
121
  <div class="pt-4 pb-1 border-t border-gray-200 dark:border-gray-600">
147
122
  <div class="px-4">
148
- <div
149
- class="font-medium text-base text-gray-800 dark:text-gray-200"
150
- >
123
+ <div class="font-medium text-base text-gray-800 dark:text-gray-200">
151
124
  {{ $page.props.auth.user.name }}
152
125
  </div>
153
126
  <div class="font-medium text-sm text-gray-500">
@@ -156,16 +129,8 @@ const { pathname = '' } = typeof window !== 'undefined' ? window.location : {}
156
129
  </div>
157
130
 
158
131
  <div class="mt-3 space-y-1">
159
- <ResponsiveNavLink :href="profile_edit_path()">
160
- Profile
161
- </ResponsiveNavLink>
162
- <ResponsiveNavLink
163
- :href="logout_path()"
164
- method="post"
165
- as="button"
166
- >
167
- Log Out
168
- </ResponsiveNavLink>
132
+ <ResponsiveNavLink :href="profile_edit_path()"> Profile </ResponsiveNavLink>
133
+ <ResponsiveNavLink :href="logout_path()" method="post" as="button"> Log Out </ResponsiveNavLink>
169
134
  </div>
170
135
  </div>
171
136
  </div>
@@ -4,18 +4,14 @@ import { Link } from '@inertiajs/vue3'
4
4
  </script>
5
5
 
6
6
  <template>
7
- <div
8
- class="min-h-screen flex flex-col sm:justify-center items-center pt-6 sm:pt-0 bg-gray-100 dark:bg-gray-900"
9
- >
7
+ <div class="min-h-screen flex flex-col sm:justify-center items-center pt-6 sm:pt-0 bg-gray-100 dark:bg-gray-900">
10
8
  <div>
11
9
  <Link href="/">
12
- <ApplicationLogo class="w-20 h-20 fill-current text-gray-500" />
10
+ <ApplicationLogo class="w-20 h-20 fill-current text-red-500" />
13
11
  </Link>
14
12
  </div>
15
13
 
16
- <div
17
- class="w-full sm:max-w-md mt-6 px-6 py-4 bg-white dark:bg-gray-800 shadow-md overflow-hidden sm:rounded-lg"
18
- >
14
+ <div class="w-full sm:max-w-md mt-6 px-6 py-4 bg-white dark:bg-gray-800 shadow-md overflow-hidden sm:rounded-lg">
19
15
  <slot />
20
16
  </div>
21
17
  </div>
@@ -25,15 +25,11 @@ const submit = () => {
25
25
  <Head title="Forgot Password" />
26
26
 
27
27
  <div class="mb-4 text-sm text-gray-600 dark:text-gray-400">
28
- Forgot your password? No problem. Just let us know your email address and
29
- we will email you a password reset link that will allow you to choose a
30
- new one.
28
+ Forgot your password? No problem. Just let us know your email address and we will email you a password reset link
29
+ that will allow you to choose a new one.
31
30
  </div>
32
31
 
33
- <div
34
- v-if="status"
35
- class="mb-4 font-medium text-sm text-green-600 dark:text-green-400"
36
- >
32
+ <div v-if="status" class="mb-4 font-medium text-sm text-green-600 dark:text-green-400">
37
33
  {{ status }}
38
34
  </div>
39
35
 
@@ -55,10 +51,7 @@ const submit = () => {
55
51
  </div>
56
52
 
57
53
  <div class="flex items-center justify-end mt-4">
58
- <PrimaryButton
59
- :class="{ 'opacity-25': form.processing }"
60
- :disabled="form.processing"
61
- >
54
+ <PrimaryButton :class="{ 'opacity-25': form.processing }" :disabled="form.processing">
62
55
  Email Password Reset Link
63
56
  </PrimaryButton>
64
57
  </div>
@@ -9,7 +9,6 @@ import { Head, Link, useForm } from '@inertiajs/vue3'
9
9
  import { login_path, password_request_path } from '@/routes'
10
10
 
11
11
  defineProps<{
12
- canResetPassword?: boolean
13
12
  status?: string
14
13
  }>()
15
14
 
@@ -71,26 +70,19 @@ const submit = () => {
71
70
  <div class="block mt-4">
72
71
  <label class="flex items-center">
73
72
  <Checkbox name="remember" v-model:checked="form.remember" />
74
- <span class="ms-2 text-sm text-gray-600 dark:text-gray-400"
75
- >Remember me</span
76
- >
73
+ <span class="ms-2 text-sm text-gray-600 dark:text-gray-400">Remember me</span>
77
74
  </label>
78
75
  </div>
79
76
 
80
77
  <div class="flex items-center justify-end mt-4">
81
78
  <Link
82
- v-if="canResetPassword"
83
79
  :href="password_request_path()"
84
80
  class="underline text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 dark:focus:ring-offset-gray-800"
85
81
  >
86
82
  Forgot your password?
87
83
  </Link>
88
84
 
89
- <PrimaryButton
90
- class="ms-4"
91
- :class="{ 'opacity-25': form.processing }"
92
- :disabled="form.processing"
93
- >
85
+ <PrimaryButton class="ms-4" :class="{ 'opacity-25': form.processing }" :disabled="form.processing">
94
86
  Log in
95
87
  </PrimaryButton>
96
88
  </div>
@@ -97,11 +97,7 @@ const submit = () => {
97
97
  Already registered?
98
98
  </Link>
99
99
 
100
- <PrimaryButton
101
- class="ms-4"
102
- :class="{ 'opacity-25': form.processing }"
103
- :disabled="form.processing"
104
- >
100
+ <PrimaryButton class="ms-4" :class="{ 'opacity-25': form.processing }" :disabled="form.processing">
105
101
  Register
106
102
  </PrimaryButton>
107
103
  </div>
@@ -80,10 +80,7 @@ const submit = () => {
80
80
  </div>
81
81
 
82
82
  <div class="flex items-center justify-end mt-4">
83
- <PrimaryButton
84
- :class="{ 'opacity-25': form.processing }"
85
- :disabled="form.processing"
86
- >
83
+ <PrimaryButton :class="{ 'opacity-25': form.processing }" :disabled="form.processing">
87
84
  Reset Password
88
85
  </PrimaryButton>
89
86
  </div>
@@ -0,0 +1,50 @@
1
+ <script setup lang="ts">
2
+ import { computed } from 'vue'
3
+ import GuestLayout from '@/Layouts/GuestLayout.vue'
4
+ import PrimaryButton from '@/Components/PrimaryButton.vue'
5
+ import { Head, Link, useForm } from '@inertiajs/vue3'
6
+ import { logout_path, verification_send_path } from '@/routes'
7
+
8
+ const props = defineProps<{
9
+ status?: string
10
+ }>()
11
+
12
+ const form = useForm({})
13
+
14
+ const submit = () => {
15
+ form.post(verification_send_path())
16
+ }
17
+
18
+ const verificationLinkSent = computed(() => props.status === 'verification-link-sent')
19
+ </script>
20
+
21
+ <template>
22
+ <GuestLayout>
23
+ <Head title="Email Verification" />
24
+
25
+ <div class="mb-4 text-sm text-gray-600 dark:text-gray-400">
26
+ Thanks for signing up! Before getting started, could you verify your email address by clicking on the link we just
27
+ emailed to you? If you didn't receive the email, we will gladly send you another.
28
+ </div>
29
+
30
+ <div class="mb-4 font-medium text-sm text-green-600 dark:text-green-400" v-if="verificationLinkSent">
31
+ A new verification link has been sent to the email address you provided during registration.
32
+ </div>
33
+
34
+ <form @submit.prevent="submit">
35
+ <div class="mt-4 flex items-center justify-between">
36
+ <PrimaryButton :class="{ 'opacity-25': form.processing }" :disabled="form.processing">
37
+ Resend Verification Email
38
+ </PrimaryButton>
39
+
40
+ <Link
41
+ :href="logout_path()"
42
+ method="post"
43
+ as="button"
44
+ class="underline text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 dark:focus:ring-offset-gray-800"
45
+ >Log Out</Link
46
+ >
47
+ </div>
48
+ </form>
49
+ </GuestLayout>
50
+ </template>
@@ -8,21 +8,13 @@ import { Head } from '@inertiajs/vue3'
8
8
 
9
9
  <AuthenticatedLayout>
10
10
  <template #header>
11
- <h2
12
- class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight"
13
- >
14
- Dashboard
15
- </h2>
11
+ <h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">Dashboard</h2>
16
12
  </template>
17
13
 
18
14
  <div class="py-12">
19
15
  <div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
20
- <div
21
- class="bg-white dark:bg-gray-800 overflow-hidden shadow-sm sm:rounded-lg"
22
- >
23
- <div class="p-6 text-gray-900 dark:text-gray-100">
24
- You're logged in!
25
- </div>
16
+ <div class="bg-white dark:bg-gray-800 overflow-hidden shadow-sm sm:rounded-lg">
17
+ <div class="p-6 text-gray-900 dark:text-gray-100">You're logged in!</div>
26
18
  </div>
27
19
  </div>
28
20
  </div>
@@ -16,21 +16,13 @@ defineProps<{
16
16
 
17
17
  <AuthenticatedLayout>
18
18
  <template #header>
19
- <h2
20
- class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight"
21
- >
22
- Profile
23
- </h2>
19
+ <h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">Profile</h2>
24
20
  </template>
25
21
 
26
22
  <div class="py-12">
27
23
  <div class="max-w-7xl mx-auto sm:px-6 lg:px-8 space-y-6">
28
24
  <div class="p-4 sm:p-8 bg-white dark:bg-gray-800 shadow sm:rounded-lg">
29
- <UpdateProfileInformationForm
30
- :must-verify-email="mustVerifyEmail"
31
- :status="status"
32
- class="max-w-xl"
33
- />
25
+ <UpdateProfileInformationForm :must-verify-email="mustVerifyEmail" :status="status" class="max-w-xl" />
34
26
  </div>
35
27
 
36
28
  <div class="p-4 sm:p-8 bg-white dark:bg-gray-800 shadow sm:rounded-lg">
@@ -43,14 +43,11 @@ const closeModal = () => {
43
43
  <template>
44
44
  <section class="space-y-6">
45
45
  <header>
46
- <h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
47
- Delete Account
48
- </h2>
46
+ <h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">Delete Account</h2>
49
47
 
50
48
  <p class="mt-1 text-sm text-gray-600 dark:text-gray-400">
51
- Once your account is deleted, all of its resources and data will be
52
- permanently deleted. Before deleting your account, please download any
53
- data or information that you wish to retain.
49
+ Once your account is deleted, all of its resources and data will be permanently deleted. Before deleting your
50
+ account, please download any data or information that you wish to retain.
54
51
  </p>
55
52
  </header>
56
53
 
@@ -63,9 +60,8 @@ const closeModal = () => {
63
60
  </h2>
64
61
 
65
62
  <p class="mt-1 text-sm text-gray-600 dark:text-gray-400">
66
- Once your account is deleted, all of its resources and data will be
67
- permanently deleted. Please enter your password to confirm you would
68
- like to permanently delete your account.
63
+ Once your account is deleted, all of its resources and data will be permanently deleted. Please enter your
64
+ password to confirm you would like to permanently delete your account.
69
65
  </p>
70
66
 
71
67
  <div class="mt-6">
@@ -39,9 +39,7 @@ const updatePassword = () => {
39
39
  <template>
40
40
  <section>
41
41
  <header>
42
- <h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
43
- Update Password
44
- </h2>
42
+ <h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">Update Password</h2>
45
43
 
46
44
  <p class="mt-1 text-sm text-gray-600 dark:text-gray-400">
47
45
  Ensure your account is using a long, random password to stay secure.
@@ -102,12 +100,7 @@ const updatePassword = () => {
102
100
  leave-active-class="transition ease-in-out"
103
101
  leave-to-class="opacity-0"
104
102
  >
105
- <p
106
- v-if="form.recentlySuccessful"
107
- class="text-sm text-gray-600 dark:text-gray-400"
108
- >
109
- Saved.
110
- </p>
103
+ <p v-if="form.recentlySuccessful" class="text-sm text-gray-600 dark:text-gray-400">Saved.</p>
111
104
  </Transition>
112
105
  </div>
113
106
  </form>
@@ -22,19 +22,14 @@ const form = useForm({
22
22
  <template>
23
23
  <section>
24
24
  <header>
25
- <h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
26
- Profile Information
27
- </h2>
25
+ <h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">Profile Information</h2>
28
26
 
29
27
  <p class="mt-1 text-sm text-gray-600 dark:text-gray-400">
30
28
  Update your account's profile information and email address.
31
29
  </p>
32
30
  </header>
33
31
 
34
- <form
35
- @submit.prevent="form.patch(profile_update_path())"
36
- class="mt-6 space-y-6"
37
- >
32
+ <form @submit.prevent="form.patch(profile_update_path())" class="mt-6 space-y-6">
38
33
  <div>
39
34
  <InputLabel for="name" value="Name" />
40
35
 
@@ -75,12 +70,7 @@ const form = useForm({
75
70
  leave-active-class="transition ease-in-out"
76
71
  leave-to-class="opacity-0"
77
72
  >
78
- <p
79
- v-if="form.recentlySuccessful"
80
- class="text-sm text-gray-600 dark:text-gray-400"
81
- >
82
- Saved.
83
- </p>
73
+ <p v-if="form.recentlySuccessful" class="text-sm text-gray-600 dark:text-gray-400">Saved.</p>
84
74
  </Transition>
85
75
  </div>
86
76
  </form>
@@ -18,9 +18,7 @@ defineProps<{
18
18
  font-size: calc(0.9em + 0.5vw);
19
19
  "
20
20
  >
21
- <header
22
- class="absolute top-0 right-0 grid grid-cols-2 items-center gap-2 py-10 lg:grid-cols-3"
23
- >
21
+ <header class="absolute top-0 right-0 grid grid-cols-2 items-center gap-2 py-10 lg:grid-cols-3">
24
22
  <div class="-mx-3 flex flex-1 justify-end">
25
23
  <Link
26
24
  :href="dashboard_path()"
@@ -63,8 +61,7 @@ defineProps<{
63
61
  target="_blank"
64
62
  style="
65
63
  transition: background 0.25s cubic-bezier(0.33, 1, 0.68, 1);
66
- filter: drop-shadow(0 20px 13px rgb(0 0 0 / 0.03))
67
- drop-shadow(0 8px 5px rgb(0 0 0 / 0.08));
64
+ filter: drop-shadow(0 20px 13px rgb(0 0 0 / 0.03)) drop-shadow(0 8px 5px rgb(0 0 0 / 0.08));
68
65
  "
69
66
  >
70
67
  <img
@@ -3,12 +3,7 @@ import forms from '@tailwindcss/forms'
3
3
 
4
4
  /** @type {import('tailwindcss').Config} */
5
5
  export default {
6
- content: [
7
- './public/*.html',
8
- './app/helpers/**/*.rb',
9
- './app/views/**/*',
10
- './app/javascript/**/*.vue',
11
- ],
6
+ content: ['./public/*.html', './app/helpers/**/*.rb', './app/views/**/*', './app/javascript/**/*.vue'],
12
7
 
13
8
  theme: {
14
9
  extend: {
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kaze
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cuong Giang
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-06-15 00:00:00.000000000 Z
11
+ date: 2024-06-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -60,7 +60,6 @@ executables:
60
60
  extensions: []
61
61
  extra_rdoc_files: []
62
62
  files:
63
- - MIT-LICENSE
64
63
  - README.md
65
64
  - bin/kaze
66
65
  - lib/kaze.rb
@@ -84,9 +83,10 @@ files:
84
83
  - stubs/default/app/mailers/application_mailer.rb
85
84
  - stubs/default/app/mailers/user_mailer.rb
86
85
  - stubs/default/app/models/application_record.rb
87
- - stubs/default/app/models/auth.rb
88
86
  - stubs/default/app/models/concerns/can_reset_password.rb
87
+ - stubs/default/app/models/concerns/must_verify_email.rb
89
88
  - stubs/default/app/models/current.rb
89
+ - stubs/default/app/models/session_guard.rb
90
90
  - stubs/default/app/models/user.rb
91
91
  - stubs/default/app/validators/current_password_validator.rb
92
92
  - stubs/default/app/validators/email_validator.rb
@@ -95,12 +95,14 @@ files:
95
95
  - stubs/default/app/views/layouts/mailer.html.erb
96
96
  - stubs/default/app/views/layouts/mailer.text.erb
97
97
  - stubs/default/app/views/user_mailer/reset_password.html.erb
98
+ - stubs/default/app/views/user_mailer/verify_email.html.erb
98
99
  - stubs/default/bin/dev
99
100
  - stubs/default/config/routes.rb
100
101
  - stubs/default/db/migrate/20240101000000_create_users.rb
101
102
  - stubs/default/db/migrate/20240101000001_create_delayed_jobs.rb
102
103
  - stubs/default/test/factories/users.rb
103
104
  - stubs/default/test/integration/auth/authentication_test.rb
105
+ - stubs/default/test/integration/auth/email_verification_test.rb
104
106
  - stubs/default/test/integration/auth/password_reset_test.rb
105
107
  - stubs/default/test/integration/auth/registration_test.rb
106
108
  - stubs/default/test/integration/password_update_test.rb
@@ -123,12 +125,15 @@ files:
123
125
  - stubs/hotwire/app/components/text_input_component.rb
124
126
  - stubs/hotwire/app/controllers/application_controller.rb
125
127
  - stubs/hotwire/app/controllers/auth/authenticated_session_controller.rb
128
+ - stubs/hotwire/app/controllers/auth/email_verification_notification_controller.rb
126
129
  - stubs/hotwire/app/controllers/auth/new_password_controller.rb
127
130
  - stubs/hotwire/app/controllers/auth/password_reset_link_controller.rb
128
131
  - stubs/hotwire/app/controllers/auth/registered_user_controller.rb
132
+ - stubs/hotwire/app/controllers/auth/verified_email_controller.rb
129
133
  - stubs/hotwire/app/controllers/concerns/authenticate.rb
130
134
  - stubs/hotwire/app/controllers/concerns/redirect_if_authenticated.rb
131
135
  - stubs/hotwire/app/controllers/concerns/set_current_auth.rb
136
+ - stubs/hotwire/app/controllers/concerns/validate_signature.rb
132
137
  - stubs/hotwire/app/controllers/dashboard_controller.rb
133
138
  - stubs/hotwire/app/controllers/password_controller.rb
134
139
  - stubs/hotwire/app/controllers/profile_controller.rb
@@ -139,6 +144,7 @@ files:
139
144
  - stubs/hotwire/app/views/auth/login.html.erb
140
145
  - stubs/hotwire/app/views/auth/register.html.erb
141
146
  - stubs/hotwire/app/views/auth/reset_password.html.erb
147
+ - stubs/hotwire/app/views/auth/verify_email.html.erb
142
148
  - stubs/hotwire/app/views/dashboard/index.html.erb
143
149
  - stubs/hotwire/app/views/layouts/_navigation.html.erb
144
150
  - stubs/hotwire/app/views/layouts/application.html.erb
@@ -152,13 +158,16 @@ files:
152
158
  - stubs/hotwire/config/tailwind.config.js
153
159
  - stubs/inertia-common/app/controllers/application_controller.rb
154
160
  - stubs/inertia-common/app/controllers/auth/authenticated_session_controller.rb
161
+ - stubs/inertia-common/app/controllers/auth/email_verification_notification_controller.rb
155
162
  - stubs/inertia-common/app/controllers/auth/new_password_controller.rb
156
163
  - stubs/inertia-common/app/controllers/auth/password_reset_link_controller.rb
157
164
  - stubs/inertia-common/app/controllers/auth/registered_user_controller.rb
165
+ - stubs/inertia-common/app/controllers/auth/verified_email_controller.rb
158
166
  - stubs/inertia-common/app/controllers/concerns/authenticate.rb
159
167
  - stubs/inertia-common/app/controllers/concerns/handle_inertia_requests.rb
160
168
  - stubs/inertia-common/app/controllers/concerns/redirect_if_authenticated.rb
161
169
  - stubs/inertia-common/app/controllers/concerns/set_current_auth.rb
170
+ - stubs/inertia-common/app/controllers/concerns/validate_signature.rb
162
171
  - stubs/inertia-common/app/controllers/concerns/verify_csrf_token.rb
163
172
  - stubs/inertia-common/app/controllers/dashboard_controller.rb
164
173
  - stubs/inertia-common/app/controllers/password_controller.rb
@@ -186,6 +195,7 @@ files:
186
195
  - stubs/inertia-react-ts/app/javascript/Pages/Auth/Login.tsx
187
196
  - stubs/inertia-react-ts/app/javascript/Pages/Auth/Register.tsx
188
197
  - stubs/inertia-react-ts/app/javascript/Pages/Auth/ResetPassword.tsx
198
+ - stubs/inertia-react-ts/app/javascript/Pages/Auth/VerifyEmail.tsx
189
199
  - stubs/inertia-react-ts/app/javascript/Pages/Dashboard.tsx
190
200
  - stubs/inertia-react-ts/app/javascript/Pages/Profile/Edit.tsx
191
201
  - stubs/inertia-react-ts/app/javascript/Pages/Profile/Partials/DeleteUserForm.tsx
@@ -221,6 +231,7 @@ files:
221
231
  - stubs/inertia-vue-ts/app/javascript/Pages/Auth/Login.vue
222
232
  - stubs/inertia-vue-ts/app/javascript/Pages/Auth/Register.vue
223
233
  - stubs/inertia-vue-ts/app/javascript/Pages/Auth/ResetPassword.vue
234
+ - stubs/inertia-vue-ts/app/javascript/Pages/Auth/VerifyEmail.vue
224
235
  - stubs/inertia-vue-ts/app/javascript/Pages/Dashboard.vue
225
236
  - stubs/inertia-vue-ts/app/javascript/Pages/Profile/Edit.vue
226
237
  - stubs/inertia-vue-ts/app/javascript/Pages/Profile/Partials/DeleteUserForm.vue
data/MIT-LICENSE DELETED
@@ -1,20 +0,0 @@
1
- Copyright (c) 2024 Cuong Giang
2
-
3
- Permission is hereby granted, free of charge, to any person obtaining
4
- a copy of this software and associated documentation files (the
5
- "Software"), to deal in the Software without restriction, including
6
- without limitation the rights to use, copy, modify, merge, publish,
7
- distribute, sublicense, and/or sell copies of the Software, and to
8
- permit persons to whom the Software is furnished to do so, subject to
9
- the following conditions:
10
-
11
- The above copyright notice and this permission notice shall be
12
- included in all copies or substantial portions of the Software.
13
-
14
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -1,57 +0,0 @@
1
- class Auth
2
- attr_reader :name, :session, :user
3
-
4
- def initialize(name, session)
5
- @name = name
6
- @session = session
7
- end
8
-
9
- def get_user
10
- return @user unless @user.nil?
11
-
12
- id = @session[get_name]
13
-
14
- @user = User.find_by(id: id) unless id.nil?
15
-
16
- @user
17
- end
18
-
19
- def get_name
20
- "login_#{@name}_#{Digest::SHA1.hexdigest(self.class.name)}"
21
- end
22
-
23
- def check?
24
- not get_user.nil?
25
- end
26
-
27
- def attempt(credentials = {})
28
- user = User.authenticate_by(credentials)
29
-
30
- return false if user.nil?
31
-
32
- login user
33
-
34
- true
35
- end
36
-
37
- def login(user)
38
- update_session user.id
39
-
40
- set_user user
41
- end
42
-
43
- def set_user(user)
44
- @user = user
45
- end
46
-
47
- def logout
48
- @session[get_name] = nil
49
- @user = nil
50
- end
51
-
52
- private
53
-
54
- def update_session(id)
55
- @session[get_name] = id
56
- end
57
- end