forked from ubicloud/ubicloud
-
Notifications
You must be signed in to change notification settings - Fork 0
/
clover_web.rb
207 lines (171 loc) · 6.84 KB
/
clover_web.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
# frozen_string_literal: true
require "tilt/sass"
class CloverWeb < Roda
include CloverBase
opts[:check_dynamic_arity] = false
opts[:check_arity] = :warn
plugin :default_headers,
"Content-Type" => "text/html",
# 'Strict-Transport-Security'=>'max-age=16070400;', # Uncomment if only allowing https:// access
"X-Frame-Options" => "deny",
"X-Content-Type-Options" => "nosniff",
"X-XSS-Protection" => "1; mode=block"
plugin :content_security_policy do |csp|
csp.default_src :none
csp.style_src :self
csp.img_src :self, "data: image/svg+xml"
csp.form_action :self, "https://checkout.stripe.com"
csp.script_src :self, "https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js", "https://cdn.jsdelivr.net/npm/[email protected]/dist/purify.min.js"
csp.connect_src :self
csp.base_uri :none
csp.frame_ancestors :none
end
plugin :route_csrf
plugin :disallow_file_uploads
plugin :flash
plugin :assets, js: "app.js", css: "app.css", css_opts: {style: :compressed, cache: false}, timestamp_paths: true
plugin :render, escape: true, layout: "./layouts/app"
plugin :public
plugin :Integer_matcher_max
plugin :typecast_params_sized_integers, sizes: [64], default_size: 64
plugin :hash_branch_view_subdir
plugin :not_found do
@error = {
code: 404,
title: "Resource not found",
message: "Sorry, we couldn’t find the resource you’re looking for."
}
view "/error"
end
if Config.development?
# :nocov:
plugin :exception_page
class RodaRequest
def assets
exception_page_assets
super
end
end
# :nocov:
end
plugin :error_handler do |e|
@error = parse_error(e)
case e
when Sequel::ValidationFailed
flash["error"] = @error[:message]
return redirect_back_with_inputs
when Validation::ValidationFailed
flash["errors"] = (flash["errors"] || {}).merge(@error[:details])
return redirect_back_with_inputs
end
# :nocov:
next exception_page(e, assets: true) if Config.development? && @error[:code] == 500
# :nocov:
view "/error"
end
plugin :sessions,
key: "_Clover.session",
cookie_options: {secure: !(Config.development? || Config.test?)},
secret: Config.clover_session_secret
autoload_routes("web")
plugin :rodauth do
enable :argon2, :change_login, :change_password, :close_account, :create_account,
:lockout, :login, :logout, :remember, :reset_password,
:otp, :recovery_codes, :sms_codes,
:disallow_password_reuse, :password_grace_period, :active_sessions,
:verify_login_change, :change_password_notify, :confirm_password
title_instance_variable :@page_title
# :nocov:
unless Config.development?
enable :disallow_common_passwords, :verify_account
email_from Config.mail_from
verify_account_view { view "auth/verify_account", "Verify Account" }
resend_verify_account_view { view "auth/verify_account_resend", "Resend Verification" }
verify_account_email_sent_redirect { login_route }
verify_account_email_recently_sent_redirect { login_route }
verify_account_set_password? false
send_verify_account_email do
scope.send_email(email_to, "Welcome to Ubicloud: Please Verify Your Account",
greeting: "Welcome to Ubicloud,",
body: ["To complete your registration and activate your account, click the button below.",
"If you did not initiate this registration process, you may disregard this message.",
"We're excited to serve you. Should you require any assistance, our customer support team stands ready to help at [email protected]."],
button_title: "Verify Account",
button_link: verify_account_email_link)
end
end
# :nocov:
hmac_secret Config.clover_session_secret
login_view { view "auth/login", "Login" }
login_redirect { "/after-login" }
login_return_to_requested_location? true
two_factor_auth_return_to_requested_location? true
already_logged_in { redirect login_redirect }
after_login { remember_login if request.params["remember-me"] == "on" }
create_account_view { view "auth/create_account", "Create Account" }
create_account_redirect { login_route }
create_account_set_password? true
before_create_account do
account[:id] = Account.generate_uuid
account[:name] = param("name")
end
after_create_account do
Account[account_id].create_project_with_default_policy("Default")
end
reset_password_view { view "auth/reset_password", "Request Password" }
reset_password_request_view { view "auth/reset_password_request", "Request Password Reset" }
reset_password_redirect { login_route }
reset_password_email_sent_redirect { login_route }
reset_password_email_recently_sent_redirect { reset_password_request_route }
send_reset_password_email do
user = Account[account_id]
scope.send_email(user.email, "Reset Ubicloud Account Password",
greeting: "Hello #{user.name},",
body: ["We received a request to reset your account password. To reset your password, click the button below.",
"If you did not initiate this request, no action is needed. Your account remains secure.",
"For any questions or assistance, reach out to our team at [email protected]."],
button_title: "Reset Password",
button_link: reset_password_email_link)
end
change_password_redirect "/account/change-password"
change_password_route "account/change-password"
change_password_view { view "account/change_password", "My Account" }
change_login_redirect "/account/change-login"
change_login_route "account/change-login"
change_login_view { view "account/change_login", "My Account" }
close_account_redirect "/login"
close_account_route "account/close-account"
close_account_view { view "account/close_account", "My Account" }
# YYY: Should password secret and session secret be the same? Are
# there rotation issues? See also:
#
# https://github.com/jeremyevans/rodauth/commit/6cbf61090a355a20ab92e3420d5e17ec702f3328
# https://github.com/jeremyevans/rodauth/commit/d8568a325749c643c9a5c9d6d780e287f8c59c31
argon2_secret { Config.clover_session_secret }
require_bcrypt? false
end
def redirect_back_with_inputs
flash["old"] = request.params
request.redirect env["HTTP_REFERER"]
end
hash_branch("dashboard") do |r|
view "/dashboard"
end
hash_branch("after-login") do |r|
r.redirect "#{@current_user.projects.first.path}/dashboard"
end
route do |r|
r.public
r.assets
check_csrf!
rodauth.load_memory
rodauth.check_active_session
@current_user = Account[rodauth.session_value]
r.rodauth
r.root do
r.redirect rodauth.login_route
end
rodauth.require_authentication
r.hash_branches("")
end
end