masks 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +50 -0
  4. data/Rakefile +11 -0
  5. data/app/assets/builds/application.css +4764 -0
  6. data/app/assets/builds/application.js +8236 -0
  7. data/app/assets/builds/application.js.map +7 -0
  8. data/app/assets/builds/masks/application.css +1 -0
  9. data/app/assets/builds/masks/application.js +7122 -0
  10. data/app/assets/builds/masks/application.js.map +7 -0
  11. data/app/assets/images/masks.png +0 -0
  12. data/app/assets/javascripts/application.js +2 -0
  13. data/app/assets/javascripts/controllers/application.js +9 -0
  14. data/app/assets/javascripts/controllers/emails_controller.js +28 -0
  15. data/app/assets/javascripts/controllers/index.js +12 -0
  16. data/app/assets/javascripts/controllers/keys_controller.js +20 -0
  17. data/app/assets/javascripts/controllers/recover_controller.js +21 -0
  18. data/app/assets/javascripts/controllers/recover_password_controller.js +21 -0
  19. data/app/assets/javascripts/controllers/session_controller.js +94 -0
  20. data/app/assets/manifest.js +2 -0
  21. data/app/assets/masks_manifest.js +2 -0
  22. data/app/assets/stylesheets/application.css +26 -0
  23. data/app/controllers/concerns/masks/controller.rb +114 -0
  24. data/app/controllers/masks/actors_controller.rb +15 -0
  25. data/app/controllers/masks/application_controller.rb +35 -0
  26. data/app/controllers/masks/backup_codes_controller.rb +34 -0
  27. data/app/controllers/masks/debug_controller.rb +9 -0
  28. data/app/controllers/masks/devices_controller.rb +20 -0
  29. data/app/controllers/masks/emails_controller.rb +60 -0
  30. data/app/controllers/masks/error_controller.rb +14 -0
  31. data/app/controllers/masks/keys_controller.rb +45 -0
  32. data/app/controllers/masks/manage/actor_controller.rb +35 -0
  33. data/app/controllers/masks/manage/actors_controller.rb +12 -0
  34. data/app/controllers/masks/manage/base_controller.rb +12 -0
  35. data/app/controllers/masks/one_time_code_controller.rb +49 -0
  36. data/app/controllers/masks/passwords_controller.rb +33 -0
  37. data/app/controllers/masks/recoveries_controller.rb +43 -0
  38. data/app/controllers/masks/sessions_controller.rb +53 -0
  39. data/app/helpers/masks/application_helper.rb +49 -0
  40. data/app/jobs/masks/application_job.rb +7 -0
  41. data/app/jobs/masks/expire_actors_job.rb +15 -0
  42. data/app/jobs/masks/expire_recoveries_job.rb +15 -0
  43. data/app/mailers/masks/actor_mailer.rb +22 -0
  44. data/app/mailers/masks/application_mailer.rb +15 -0
  45. data/app/models/concerns/masks/access.rb +162 -0
  46. data/app/models/concerns/masks/actor.rb +132 -0
  47. data/app/models/concerns/masks/adapter.rb +68 -0
  48. data/app/models/concerns/masks/role.rb +9 -0
  49. data/app/models/concerns/masks/scoped.rb +54 -0
  50. data/app/models/masks/access/actor_password.rb +20 -0
  51. data/app/models/masks/access/actor_scopes.rb +18 -0
  52. data/app/models/masks/access/actor_signup.rb +22 -0
  53. data/app/models/masks/actors/anonymous.rb +40 -0
  54. data/app/models/masks/actors/system.rb +24 -0
  55. data/app/models/masks/adapters/active_record.rb +85 -0
  56. data/app/models/masks/application_model.rb +15 -0
  57. data/app/models/masks/application_record.rb +8 -0
  58. data/app/models/masks/check.rb +192 -0
  59. data/app/models/masks/credential.rb +166 -0
  60. data/app/models/masks/credentials/backup_code.rb +30 -0
  61. data/app/models/masks/credentials/device.rb +59 -0
  62. data/app/models/masks/credentials/email.rb +48 -0
  63. data/app/models/masks/credentials/factor2.rb +71 -0
  64. data/app/models/masks/credentials/key.rb +38 -0
  65. data/app/models/masks/credentials/last_login.rb +12 -0
  66. data/app/models/masks/credentials/masquerade.rb +32 -0
  67. data/app/models/masks/credentials/nickname.rb +63 -0
  68. data/app/models/masks/credentials/one_time_code.rb +34 -0
  69. data/app/models/masks/credentials/password.rb +28 -0
  70. data/app/models/masks/credentials/recovery.rb +71 -0
  71. data/app/models/masks/credentials/session.rb +67 -0
  72. data/app/models/masks/device.rb +30 -0
  73. data/app/models/masks/error.rb +51 -0
  74. data/app/models/masks/event.rb +14 -0
  75. data/app/models/masks/mask.rb +255 -0
  76. data/app/models/masks/rails/actor.rb +190 -0
  77. data/app/models/masks/rails/actor_role.rb +12 -0
  78. data/app/models/masks/rails/device.rb +47 -0
  79. data/app/models/masks/rails/email.rb +96 -0
  80. data/app/models/masks/rails/key.rb +61 -0
  81. data/app/models/masks/rails/recovery.rb +116 -0
  82. data/app/models/masks/rails/role.rb +20 -0
  83. data/app/models/masks/rails/scope.rb +15 -0
  84. data/app/models/masks/session.rb +447 -0
  85. data/app/models/masks/sessions/access.rb +26 -0
  86. data/app/models/masks/sessions/inline.rb +16 -0
  87. data/app/models/masks/sessions/request.rb +42 -0
  88. data/app/resources/masks/actor_resource.rb +9 -0
  89. data/app/resources/masks/session_resource.rb +15 -0
  90. data/app/views/layouts/masks/application.html.erb +17 -0
  91. data/app/views/layouts/masks/mailer.html.erb +17 -0
  92. data/app/views/layouts/masks/mailer.text.erb +1 -0
  93. data/app/views/layouts/masks/manage.html.erb +25 -0
  94. data/app/views/masks/actor_mailer/recover_credentials.html.erb +33 -0
  95. data/app/views/masks/actor_mailer/recover_credentials.text.erb +1 -0
  96. data/app/views/masks/actor_mailer/verify_email.html.erb +34 -0
  97. data/app/views/masks/actor_mailer/verify_email.text.erb +8 -0
  98. data/app/views/masks/actors/current.html.erb +152 -0
  99. data/app/views/masks/application/_header.html.erb +31 -0
  100. data/app/views/masks/backup_codes/new.html.erb +103 -0
  101. data/app/views/masks/emails/new.html.erb +103 -0
  102. data/app/views/masks/emails/verify.html.erb +51 -0
  103. data/app/views/masks/keys/new.html.erb +127 -0
  104. data/app/views/masks/manage/actor/show.html.erb +126 -0
  105. data/app/views/masks/manage/actors/index.html.erb +40 -0
  106. data/app/views/masks/one_time_code/new.html.erb +150 -0
  107. data/app/views/masks/passwords/edit.html.erb +58 -0
  108. data/app/views/masks/recoveries/new.html.erb +71 -0
  109. data/app/views/masks/recoveries/password.html.erb +64 -0
  110. data/app/views/masks/sessions/new.html.erb +153 -0
  111. data/config/brakeman.ignore +28 -0
  112. data/config/locales/en.yml +286 -0
  113. data/config/routes.rb +46 -0
  114. data/db/migrate/20231205173845_create_actors.rb +94 -0
  115. data/lib/generators/masks/install/USAGE +8 -0
  116. data/lib/generators/masks/install/install_generator.rb +33 -0
  117. data/lib/generators/masks/install/templates/initializer.rb +5 -0
  118. data/lib/generators/masks/install/templates/masks.json +6 -0
  119. data/lib/masks/configuration.rb +236 -0
  120. data/lib/masks/engine.rb +25 -0
  121. data/lib/masks/middleware.rb +70 -0
  122. data/lib/masks/version.rb +5 -0
  123. data/lib/masks.rb +183 -0
  124. data/lib/tasks/masks_tasks.rake +71 -0
  125. data/masks.json +274 -0
  126. metadata +416 -0
@@ -0,0 +1,153 @@
1
+ <div data-controller="session">
2
+ <%= form_with url: session_path, method: :post do |form| %>
3
+ <div role="alert" class="alert mb-4 text-left" data-session-target="flash">
4
+ <% if flash[:errors]&.any? && !factor2_required? %>
5
+ <div class="flex items-center gap-4">
6
+ <%= lucide_icon("shield-x", class: "stroke-error") %>
7
+ <span><%= flash[:errors][0] %></span>
8
+ </div>
9
+ <% elsif logged_in? %>
10
+ <div class="flex items-center gap-4">
11
+ <%= lucide_icon("check", class: "stroke-success") %>
12
+ <span><%= t(".logged_in") %></span>
13
+ </div>
14
+ <% else %>
15
+ <div data-flash="enter-factor2" class="hidden flex items-center gap-4">
16
+ <%= lucide_icon("key-square", class: "stroke-warning") %>
17
+ <span><%= t(".enter_factor2") %></span>
18
+ </div>
19
+ <div data-flash="enter-credentials" class="flex items-center gap-4">
20
+ <%= lucide_icon("shield-alert", class: "stroke-warning") %>
21
+ <span><%= t(".enter_credentials") %></span>
22
+ </div>
23
+ <div data-flash="enter-password" class="hidden flex items-center gap-4">
24
+ <%= lucide_icon("shield-ellipsis", class: "stroke-warning") %>
25
+ <span><%= t(".enter_password") %></span>
26
+ </div>
27
+ <div data-flash="continue" class="hidden flex items-center gap-4">
28
+ <%= lucide_icon("shield-question", class: "stroke-accent") %>
29
+ <span><%= t(".continue") %></span>
30
+ </div>
31
+ <% end %>
32
+ </div>
33
+
34
+ <% if factor2_required? %>
35
+ <div class="w-full">
36
+ <div role="tablist" class="tabs tabs-bordered mb-4">
37
+ <% if @actor.totp_secret %>
38
+ <input
39
+ checked
40
+ name="factor2"
41
+ type="radio"
42
+ role="tab"
43
+ class="tab whitespace-nowrap"
44
+ aria-label="<%= t('.tab.one_time_code') %>"
45
+ />
46
+ <div role="tabpanel" class="tab-content p-4 bg-base-100 rounded-b">
47
+ <p class="flex items-center gap-4 text-sm mb-4">
48
+ <%= lucide_icon("qr-code") %>
49
+ <%= t(".one_time_code") %>
50
+ </p>
51
+ <label class="form-control w-full">
52
+ <input
53
+ type="text"
54
+ data-action="session#updateCode"
55
+ data-session-target="oneTimeCode"
56
+ placeholder="<%= t('.placeholder.one_time_code') %>"
57
+ name="session[one_time_code]"
58
+ class="input input-bordered w-full"
59
+ />
60
+ </label>
61
+ </div>
62
+ <% end %>
63
+
64
+ <% if @actor.saved_backup_codes? %>
65
+ <input
66
+ type="radio"
67
+ name="factor2"
68
+ role="tab"
69
+ class="tab whitespace-nowrap"
70
+ aria-label="<%= t('.tab.backup_code') %>"
71
+ />
72
+ <div role="tabpanel" class="tab-content p-4 bg-base-100 rounded-b">
73
+ <p class="flex items-center gap-4 text-sm mb-4">
74
+ <%= lucide_icon("rotate-cw") %>
75
+ <%= t(".backup_code") %>
76
+ </p>
77
+ <label class="form-control w-full">
78
+ <input
79
+ type="text"
80
+ data-action="session#updateCode"
81
+ data-session-target="backupCode"
82
+ placeholder="<%= t('.placeholder.backup_code') %>"
83
+ name="session[backup_code]"
84
+ class="input input-bordered w-full"
85
+ />
86
+ </label>
87
+ </div>
88
+ <% end %>
89
+ </div>
90
+ </div>
91
+ <% elsif !logged_in? %>
92
+ <div class="flex flex-col gap-2">
93
+ <label class="form-control w-full">
94
+ <input
95
+ type="text"
96
+ data-action="session#updateNickname"
97
+ data-session-target="nickname"
98
+ placeholder="<%= t('.placeholder.nickname') %>"
99
+ name="session[nickname]"
100
+ class="input input-bordered w-full"
101
+ />
102
+ </label>
103
+ <label class="form-control w-full">
104
+ <input
105
+ type="password"
106
+ data-action="session#updatePassword"
107
+ data-session-target="password"
108
+ placeholder="<%= t('.placeholder.password') %>"
109
+ name="session[password]"
110
+ class="input input-bordered w-full"
111
+ />
112
+ <% if @config.site_links[:recover] %>
113
+ <div class="label">
114
+ <span class="label-text-alt opacity-60 hover:opacity-100"><a
115
+ class="hover:underline"
116
+ href="<%= @config.site_links[:recover] %>"
117
+ ><%= t(".recover_credentials") %></a></span>
118
+ </div>
119
+ <% end %>
120
+ </label>
121
+ </div>
122
+ <% end %>
123
+
124
+
125
+ <% unless logged_in? %>
126
+ <div class="flex items-center gap-4">
127
+ <%= form.submit t(".submit"),
128
+ class: "btn btn-active",
129
+ data: {
130
+ session_target: "submit",
131
+ } %>
132
+ <div class="form-control" data-session-target="remember">
133
+ <label class="label cursor-pointer">
134
+ <input type="checkbox" name="session[remember_me]" class="toggle toggle-sm"/>
135
+ <span class="label-text pl-2"><%= t(".remember_me") %></span>
136
+ </label>
137
+ </div>
138
+ </div>
139
+ <% end %>
140
+ <% end %>
141
+
142
+ <% if factor2_required? %>
143
+ <div class="mt-2 opacity-60 hover:opacity-100">
144
+ <%= form_with url: session_path, method: :delete do |form| %>
145
+ <span class="text-xs">
146
+ <%= t(".start_over.text") %>
147
+ <%= form.submit t(".start_over.link"), class: "cursor-pointer underline" %>
148
+ </span>
149
+
150
+ <% end %>
151
+ </div>
152
+ <% end %>
153
+ </div>
@@ -0,0 +1,28 @@
1
+ {
2
+ "ignored_warnings": [
3
+ {
4
+ "warning_type": "Cross-Site Request Forgery",
5
+ "warning_code": 7,
6
+ "fingerprint": "2c0ec97f978f7a612f1fa0567846c86ec02c072be7784e4c707fd4ba81fe5021",
7
+ "check_name": "ForgerySetting",
8
+ "message": "`protect_from_forgery` should be called in `ApplicationController`",
9
+ "file": "dummy/app/controllers/application_controller.rb",
10
+ "line": 1,
11
+ "link": "https://brakemanscanner.org/docs/warning_types/cross-site_request_forgery/",
12
+ "code": null,
13
+ "render_path": null,
14
+ "location": {
15
+ "type": "controller",
16
+ "controller": "ApplicationController"
17
+ },
18
+ "user_input": null,
19
+ "confidence": "High",
20
+ "cwe_id": [
21
+ 352
22
+ ],
23
+ "note": ""
24
+ }
25
+ ],
26
+ "updated": "2024-02-07 16:03:41 -0500",
27
+ "brakeman_version": "6.1.2"
28
+ }
@@ -0,0 +1,286 @@
1
+ # Files in the config/locales directory are used for internationalization and
2
+ # are automatically loaded by Rails. If you want to use locales other than
3
+ # English, add the necessary files in this directory.
4
+ #
5
+ # To use the locales, use `I18n.t`:
6
+ #
7
+ # I18n.t "hello"
8
+ #
9
+ # In views, this is aliased to just `t`:
10
+ #
11
+ # <%= t("hello") %>
12
+ #
13
+ # To use a different locale, set it with `I18n.locale`:
14
+ #
15
+ # I18n.locale = :es
16
+ #
17
+ # This would use the information in config/locales/es.yml.
18
+ #
19
+ # To learn more about the API, please read the Rails Internationalization guide
20
+ # at https://guides.rubyonrails.org/i18n.html.
21
+ #
22
+ # Be aware that YAML interprets the following case-insensitive strings as
23
+ # booleans: `true`, `false`, `on`, `off`, `yes`, `no`. Therefore, these strings
24
+ # must be quoted to be interpreted as strings. For example:
25
+ #
26
+ # en:
27
+ # "yes": yup
28
+ # enabled: "ON"
29
+
30
+ en:
31
+ layouts:
32
+ masks:
33
+ application:
34
+ meta:
35
+ title: masks
36
+ manage:
37
+ meta:
38
+ title: masks
39
+ masks:
40
+ application:
41
+ header:
42
+ logged_in: welcome
43
+ actor_mailer:
44
+ recover_credentials:
45
+ recover: reset password
46
+ nickname: your nickname
47
+ subheading: hey there, you recently requested help recovering your credentials...
48
+ call_to_action: your username is listed above. you can reset your password if you forgot it.
49
+ sign_off: reply to this email if you need more help. cheers
50
+ verify_email:
51
+ subject: verify your email - things
52
+ heading: verify your email
53
+ subheading: |
54
+ hey there, you recently added this email to your account. you must verify it's yours by pressing the button below...
55
+ subheading_plain: |
56
+ hey there, you recently added this email to your account. you must verify it's yours by visiting the link below...
57
+ call_to_action: once verified, this email will be usable future logins and account recovery.
58
+ sign_off: thanks
59
+ verify: "verify"
60
+ verify_plain: "verify here — "
61
+ added: added
62
+ actors:
63
+ current:
64
+ emails:
65
+ zero: no emails found
66
+ one: "%{email}"
67
+ other: "%{email}"
68
+ add_email: add...
69
+ add_more_email: add more...
70
+ change_password: change your password...
71
+ credentials: credentials
72
+ password: password
73
+ one_time_codes: one-time code
74
+ backup_codes: backup codes
75
+ created: created
76
+ manage: manage...
77
+ enable: enable...
78
+ logout: logout
79
+ never_logged_in: never...
80
+ last_accessed: last accessed
81
+ last_login: last login
82
+ ago: ago
83
+ devices: devices
84
+ change: change...
85
+ keys: keys
86
+ add_key: add...
87
+ add_more_key: add more...
88
+
89
+ passwords:
90
+ edit:
91
+ placeholder:
92
+ password: your current password...
93
+ change: your new password...
94
+ submit: change
95
+ one_time_code:
96
+ new:
97
+ tfa: secondary credential
98
+ disabled: disabled
99
+ enabled: enabled
100
+ enable_qr: to enable, scan this qr code into your authenticator app.
101
+ enable_manual: you can also enter the secret manually.
102
+ heading: one-time code
103
+ empty_detail: you must enable two-factor authentication to use backup codes.
104
+ disabled_heading: add a one-time password
105
+ placeholder:
106
+ otp: one-time code...
107
+ password: your password...
108
+ delete: enter your password...
109
+ secret: secret
110
+ submit: enable
111
+ delete: disable
112
+ delete_div: disable one-time code
113
+ backup_codes: save backup codes...
114
+ reset_codes: view backup codes...
115
+ backup_codes:
116
+ new:
117
+ tfa: secondary credential
118
+ disabled: disabled
119
+ enabled: enabled
120
+ heading: backup codes
121
+ empty_detail: backup codes are available once you add a secondary credential, like a one-time code.
122
+ disabled_heading: backup codes are disabled
123
+ save_codes: save your 10-digit backup codes somewhere safe, then press enable to use them as another secondary credential...
124
+ reset_codes: press delete to disable backup codes. afterward you can generate a new set of codes.
125
+ download: download
126
+ enable: enable
127
+ delete: delete
128
+ placeholder:
129
+ password: enter your password...
130
+ emails:
131
+ verify:
132
+ verified: verified!
133
+ verification_expired: email verification link expired
134
+ card_title: how verified emails work...
135
+ details: |
136
+ you can use your newly verified email:
137
+ list_html: |
138
+ <li>instead of your nickname during login
139
+ <li>for password-less login via email links
140
+ <li>to recover your nickname or password
141
+ privacy: your emails will never be shared.
142
+ manage: to manage it and others...
143
+ manage_expired: to try again...
144
+ added: manage it in
145
+ emails: view your emails
146
+ new:
147
+ page: your email
148
+ placeholder:
149
+ email:
150
+ zero: enter a new email address...
151
+ one: enter another email address...
152
+ other: enter another email address...
153
+ password: enter your password...
154
+ heading: no emails found
155
+ no_emails: no emails added
156
+ no_emails_detail: your email can act as an alternate way to access and recover your account.
157
+ heading_new:
158
+ zero: no emails found
159
+ one: your email
160
+ other: your emails
161
+ help_title: how it works
162
+ help_body: if you enter valid information you will be contacted with instructions to recover your credentials.
163
+ help_more: need more help?
164
+ help_contact: contact support
165
+ help_button: "help"
166
+ support_url:
167
+ submit: add
168
+ back: go back...
169
+ email_verified: verified %{ago} ago
170
+ email_taken: email already taken.
171
+ pending_verification: awaiting verification...
172
+ expired_verification: verification expired.
173
+ add: add an email...
174
+ keys:
175
+ new:
176
+ heading: your keys
177
+ added: allow automated tools to act on your behalf...
178
+ page: your key
179
+ placeholder:
180
+ name: enter a name...
181
+ password: enter your password...
182
+ secret: leave blank to generate a secret...
183
+ no_keys_detail: keys allow automated tools to act on your behalf...
184
+ heading_new:
185
+ zero: no keys found
186
+ one: your key
187
+ other: your keys
188
+ help_title: how it works
189
+ help_body: if you enter valid information you will be contacted with instructions to recover your credentials.
190
+ help_more: need more help?
191
+ help_contact: contact support
192
+ help_button: "help"
193
+ support_url:
194
+ submit: make key
195
+ back: go back...
196
+ key_verified: verified %{ago} ago
197
+ key_taken: key already taken.
198
+ pending_verification: awaiting verification...
199
+ expired_verification: verification expired.
200
+ add: add key
201
+ recoveries:
202
+ password:
203
+ placeholder: new password...
204
+ heading: reset your password
205
+ heading_success: password reset
206
+ heading_expired: password reset expired
207
+ subheading: enter a new password. you can use it to login to your account after it's changed...
208
+ subheading_success: your password has been changed. you can login using the password you just entered.
209
+ subheading_expired: this password reset link is expired or invalid.
210
+ help_title: how it works
211
+ help_body: if you enter valid information you will be contacted with instructions to recover your credentials.
212
+ help_more: need more help?
213
+ help_contact: contact support
214
+ help_button: "help"
215
+ support_url:
216
+ submit: reset
217
+ login: back to login
218
+ new:
219
+ placeholder: nickname, email or phone...
220
+ heading: recover your credentials
221
+ subheading: enter a nickname, email, or phone number associated with your account to recover your credentials...
222
+ help_title: how it works
223
+ help_body: if you enter valid information you will be contacted with instructions to recover your credentials.
224
+ help_more: need more help?
225
+ help_contact: contact support
226
+ help_button: "help"
227
+ support_url:
228
+ submit: recover
229
+ back: go back...
230
+ submitted:
231
+ heading: check your notifications...
232
+ description: if you have an account with us you'll receive an email or message on your phone with instructions on how to recover your account.
233
+ sessions:
234
+ new:
235
+ submit: continue
236
+ remember_me: remember me
237
+ start_over:
238
+ text: or
239
+ link: start over...
240
+ or_start_over: or
241
+ recover_credentials: "forgot your credentials?"
242
+ enter_factor2: enter a secondary credential to continue...
243
+ enter_credentials: "enter your credentials to continue..."
244
+ enter_password: "enter your password to continue..."
245
+ continue: "press continue to access things..."
246
+ one_time_code: enter a 6-digit one-time code from your authenticator app...
247
+ backup_code: enter one of your saved 10-digit backup codes...
248
+ logged_in: welcome!
249
+ tab:
250
+ one_time_code: one-time code
251
+ backup_code: backup code
252
+ placeholder:
253
+ nickname: nickname, email, or phone number...
254
+ password: password...
255
+ one_time_code: one-time code...
256
+ backup_code: backup code...
257
+ activerecord:
258
+ attributes:
259
+ masks/rails/actor:
260
+ nickname: nickname
261
+ password: password
262
+ signup: invalid
263
+ masks/rails/email:
264
+ email: email
265
+ masks/rails/key:
266
+ name: name
267
+ secret: secret
268
+ scopes: scopes
269
+ errors:
270
+ models:
271
+ masks/rails/actor:
272
+ format: is invalid
273
+ attributes:
274
+ signup:
275
+ disabled: credentials...
276
+ activemodel:
277
+ attributes:
278
+ masks/credentials/password:
279
+ password: password
280
+ masks/credentials/nickname:
281
+ nickname: nickname
282
+ errors:
283
+ models:
284
+ masks/session:
285
+ credentials: invalid credentials...
286
+ access: invalid access...
data/config/routes.rb ADDED
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ Masks::Engine.routes.draw do
4
+ get "/debug", to: "debug#show" if Rails.env.development?
5
+
6
+ # signup/login
7
+ get "session", to: "sessions#new", as: :session
8
+ post "session", to: "sessions#create"
9
+ delete "session", to: "sessions#destroy"
10
+
11
+ # recover credentials
12
+ get "recover", to: "recoveries#new", as: :recover
13
+ post "recover", to: "recoveries#create"
14
+ get "recovery", to: "recoveries#password", as: :recover_password
15
+ post "recovery", to: "recoveries#reset"
16
+
17
+ # manage account details, password, etc
18
+ get "me", to: "actors#current", as: :current
19
+ get "password", to: "passwords#edit", as: :password
20
+ post "password", to: "passwords#update"
21
+ post "device/:key", to: "devices#update", as: :device
22
+
23
+ # manage emails
24
+ get "emails", to: "emails#new", as: :emails
25
+ post "emails", to: "emails#create"
26
+ patch "emails", to: "emails#notify"
27
+ delete "emails", to: "emails#delete"
28
+ get "email/:email/verify", to: "emails#verify", as: :email_verify
29
+
30
+ # keys
31
+ get "keys", to: "keys#new", as: :keys
32
+ post "keys", to: "keys#create"
33
+ delete "keys", to: "keys#delete"
34
+
35
+ # manage 2nd factor options
36
+ get "one-time-codes", to: "one_time_code#new", as: :one_time_code
37
+ post "one-time-codes", to: "one_time_code#create"
38
+ delete "one-time-codes", to: "one_time_code#destroy"
39
+ get "backup-codes", to: "backup_codes#new", as: :backup_codes
40
+ post "backup-codes", to: "backup_codes#create"
41
+
42
+ # managers-only section
43
+ get "actors", to: "manage/actors#index", as: :actors
44
+ get "actors/:actor", to: "manage/actor#show", as: :actor
45
+ patch "actors/:actor", to: "manage/actor#update"
46
+ end
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CreateActors < ActiveRecord::Migration[7.1]
4
+ def change
5
+ create_table :actors do |t|
6
+ t.string :type
7
+ t.string :nickname
8
+ t.string :version
9
+ t.string :password_digest
10
+ t.string :phone_number
11
+ t.string :totp_secret
12
+ t.text :backup_codes
13
+
14
+ t.timestamps
15
+ t.datetime :last_login_at
16
+ t.datetime :changed_password_at
17
+ t.datetime :added_phone_number_at
18
+ t.datetime :added_totp_secret_at
19
+ t.datetime :saved_backup_codes_at
20
+ t.datetime :notified_inactive_at
21
+
22
+ t.index :nickname, unique: true
23
+ end
24
+
25
+ create_table :scopes do |t|
26
+ t.string :name
27
+ t.references :actor, polymorphic: true
28
+ t.index %i[name actor_id], unique: true
29
+ t.timestamps
30
+ end
31
+
32
+ create_table :roles do |t|
33
+ t.string :type
34
+ t.references :actor, polymorphic: true
35
+ t.references :record, polymorphic: true
36
+ t.timestamps
37
+ end
38
+
39
+ add_index :roles,
40
+ %i[type actor_id actor_type record_id record_type],
41
+ unique: true
42
+
43
+ create_table :emails do |t|
44
+ t.string :email
45
+ t.string :token
46
+ t.references :actor
47
+ t.boolean :verified, null: true
48
+ t.datetime :verified_at
49
+ t.datetime :notified_at
50
+ t.timestamps
51
+
52
+ t.index %i[email verified], unique: true
53
+ t.index %i[token], unique: true
54
+ end
55
+
56
+ create_table :recoveries do |t|
57
+ t.string :token
58
+ t.string :nickname, null: true
59
+ t.string :email, null: true
60
+ t.string :phone, null: true
61
+ t.references :actor
62
+ t.datetime :notified_at
63
+ t.timestamps
64
+
65
+ t.index %i[token actor_id], unique: true
66
+ end
67
+
68
+ create_table :devices do |t|
69
+ t.string :key
70
+ t.string :user_agent
71
+ t.string :ip_address
72
+ t.string :fingerprint
73
+ t.string :version
74
+
75
+ t.references :actor
76
+ t.datetime :accessed_at
77
+ t.timestamps
78
+
79
+ t.index %i[key actor_id], unique: true
80
+ end
81
+
82
+ create_table :keys do |t|
83
+ t.string :name
84
+ t.string :sha
85
+ t.text :scopes
86
+
87
+ t.references :actor
88
+ t.timestamps
89
+ t.datetime :accessed_at
90
+
91
+ t.index %i[sha], unique: true
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,8 @@
1
+ Description:
2
+ Explain the generator
3
+
4
+ Example:
5
+ bin/rails generate install Thing
6
+
7
+ This will create:
8
+ what/will/it/create
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Masks
4
+ # Generator for +rails g masks:install+.
5
+ class InstallGenerator < ::Rails::Generators::Base
6
+ source_root File.expand_path("templates", __dir__)
7
+
8
+ def add_routing
9
+ route 'mount Masks::Engine => "/"'
10
+ end
11
+
12
+ def copy_initializer_file
13
+ copy_file "initializer.rb", "config/initializers/masks.rb"
14
+ end
15
+
16
+ def copy_masks_json
17
+ copy_file "masks.json", "masks.json"
18
+ end
19
+
20
+ def add_migrations
21
+ if yes?("generate migrations for masks?")
22
+ rails_command "masks:install:migrations"
23
+ else
24
+ puts
25
+ puts 'run "rails masks:install:migrations" to add them later on...'
26
+ end
27
+
28
+ puts
29
+ puts "[masks] welcome!"
30
+ puts "[masks] visit https://masks.geiger.to for more information."
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ Masks.configure do |config|
4
+ # see https://masks.geiger.to/get-started for configuration options
5
+ end
@@ -0,0 +1,6 @@
1
+ {
2
+ "name": "<%= Rails.application.name %>",
3
+ "url": "http://localhost:3000",
4
+ "extend": "masks",
5
+ "masks": []
6
+ }