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.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +50 -0
- data/Rakefile +11 -0
- data/app/assets/builds/application.css +4764 -0
- data/app/assets/builds/application.js +8236 -0
- data/app/assets/builds/application.js.map +7 -0
- data/app/assets/builds/masks/application.css +1 -0
- data/app/assets/builds/masks/application.js +7122 -0
- data/app/assets/builds/masks/application.js.map +7 -0
- data/app/assets/images/masks.png +0 -0
- data/app/assets/javascripts/application.js +2 -0
- data/app/assets/javascripts/controllers/application.js +9 -0
- data/app/assets/javascripts/controllers/emails_controller.js +28 -0
- data/app/assets/javascripts/controllers/index.js +12 -0
- data/app/assets/javascripts/controllers/keys_controller.js +20 -0
- data/app/assets/javascripts/controllers/recover_controller.js +21 -0
- data/app/assets/javascripts/controllers/recover_password_controller.js +21 -0
- data/app/assets/javascripts/controllers/session_controller.js +94 -0
- data/app/assets/manifest.js +2 -0
- data/app/assets/masks_manifest.js +2 -0
- data/app/assets/stylesheets/application.css +26 -0
- data/app/controllers/concerns/masks/controller.rb +114 -0
- data/app/controllers/masks/actors_controller.rb +15 -0
- data/app/controllers/masks/application_controller.rb +35 -0
- data/app/controllers/masks/backup_codes_controller.rb +34 -0
- data/app/controllers/masks/debug_controller.rb +9 -0
- data/app/controllers/masks/devices_controller.rb +20 -0
- data/app/controllers/masks/emails_controller.rb +60 -0
- data/app/controllers/masks/error_controller.rb +14 -0
- data/app/controllers/masks/keys_controller.rb +45 -0
- data/app/controllers/masks/manage/actor_controller.rb +35 -0
- data/app/controllers/masks/manage/actors_controller.rb +12 -0
- data/app/controllers/masks/manage/base_controller.rb +12 -0
- data/app/controllers/masks/one_time_code_controller.rb +49 -0
- data/app/controllers/masks/passwords_controller.rb +33 -0
- data/app/controllers/masks/recoveries_controller.rb +43 -0
- data/app/controllers/masks/sessions_controller.rb +53 -0
- data/app/helpers/masks/application_helper.rb +49 -0
- data/app/jobs/masks/application_job.rb +7 -0
- data/app/jobs/masks/expire_actors_job.rb +15 -0
- data/app/jobs/masks/expire_recoveries_job.rb +15 -0
- data/app/mailers/masks/actor_mailer.rb +22 -0
- data/app/mailers/masks/application_mailer.rb +15 -0
- data/app/models/concerns/masks/access.rb +162 -0
- data/app/models/concerns/masks/actor.rb +132 -0
- data/app/models/concerns/masks/adapter.rb +68 -0
- data/app/models/concerns/masks/role.rb +9 -0
- data/app/models/concerns/masks/scoped.rb +54 -0
- data/app/models/masks/access/actor_password.rb +20 -0
- data/app/models/masks/access/actor_scopes.rb +18 -0
- data/app/models/masks/access/actor_signup.rb +22 -0
- data/app/models/masks/actors/anonymous.rb +40 -0
- data/app/models/masks/actors/system.rb +24 -0
- data/app/models/masks/adapters/active_record.rb +85 -0
- data/app/models/masks/application_model.rb +15 -0
- data/app/models/masks/application_record.rb +8 -0
- data/app/models/masks/check.rb +192 -0
- data/app/models/masks/credential.rb +166 -0
- data/app/models/masks/credentials/backup_code.rb +30 -0
- data/app/models/masks/credentials/device.rb +59 -0
- data/app/models/masks/credentials/email.rb +48 -0
- data/app/models/masks/credentials/factor2.rb +71 -0
- data/app/models/masks/credentials/key.rb +38 -0
- data/app/models/masks/credentials/last_login.rb +12 -0
- data/app/models/masks/credentials/masquerade.rb +32 -0
- data/app/models/masks/credentials/nickname.rb +63 -0
- data/app/models/masks/credentials/one_time_code.rb +34 -0
- data/app/models/masks/credentials/password.rb +28 -0
- data/app/models/masks/credentials/recovery.rb +71 -0
- data/app/models/masks/credentials/session.rb +67 -0
- data/app/models/masks/device.rb +30 -0
- data/app/models/masks/error.rb +51 -0
- data/app/models/masks/event.rb +14 -0
- data/app/models/masks/mask.rb +255 -0
- data/app/models/masks/rails/actor.rb +190 -0
- data/app/models/masks/rails/actor_role.rb +12 -0
- data/app/models/masks/rails/device.rb +47 -0
- data/app/models/masks/rails/email.rb +96 -0
- data/app/models/masks/rails/key.rb +61 -0
- data/app/models/masks/rails/recovery.rb +116 -0
- data/app/models/masks/rails/role.rb +20 -0
- data/app/models/masks/rails/scope.rb +15 -0
- data/app/models/masks/session.rb +447 -0
- data/app/models/masks/sessions/access.rb +26 -0
- data/app/models/masks/sessions/inline.rb +16 -0
- data/app/models/masks/sessions/request.rb +42 -0
- data/app/resources/masks/actor_resource.rb +9 -0
- data/app/resources/masks/session_resource.rb +15 -0
- data/app/views/layouts/masks/application.html.erb +17 -0
- data/app/views/layouts/masks/mailer.html.erb +17 -0
- data/app/views/layouts/masks/mailer.text.erb +1 -0
- data/app/views/layouts/masks/manage.html.erb +25 -0
- data/app/views/masks/actor_mailer/recover_credentials.html.erb +33 -0
- data/app/views/masks/actor_mailer/recover_credentials.text.erb +1 -0
- data/app/views/masks/actor_mailer/verify_email.html.erb +34 -0
- data/app/views/masks/actor_mailer/verify_email.text.erb +8 -0
- data/app/views/masks/actors/current.html.erb +152 -0
- data/app/views/masks/application/_header.html.erb +31 -0
- data/app/views/masks/backup_codes/new.html.erb +103 -0
- data/app/views/masks/emails/new.html.erb +103 -0
- data/app/views/masks/emails/verify.html.erb +51 -0
- data/app/views/masks/keys/new.html.erb +127 -0
- data/app/views/masks/manage/actor/show.html.erb +126 -0
- data/app/views/masks/manage/actors/index.html.erb +40 -0
- data/app/views/masks/one_time_code/new.html.erb +150 -0
- data/app/views/masks/passwords/edit.html.erb +58 -0
- data/app/views/masks/recoveries/new.html.erb +71 -0
- data/app/views/masks/recoveries/password.html.erb +64 -0
- data/app/views/masks/sessions/new.html.erb +153 -0
- data/config/brakeman.ignore +28 -0
- data/config/locales/en.yml +286 -0
- data/config/routes.rb +46 -0
- data/db/migrate/20231205173845_create_actors.rb +94 -0
- data/lib/generators/masks/install/USAGE +8 -0
- data/lib/generators/masks/install/install_generator.rb +33 -0
- data/lib/generators/masks/install/templates/initializer.rb +5 -0
- data/lib/generators/masks/install/templates/masks.json +6 -0
- data/lib/masks/configuration.rb +236 -0
- data/lib/masks/engine.rb +25 -0
- data/lib/masks/middleware.rb +70 -0
- data/lib/masks/version.rb +5 -0
- data/lib/masks.rb +183 -0
- data/lib/tasks/masks_tasks.rake +71 -0
- data/masks.json +274 -0
- 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,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
|