belt 0.2.18 → 0.2.20
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.
Potentially problematic release.
This version of belt might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/lib/belt/cli/auth_command.rb +150 -14
- data/lib/belt/cli/console_command.rb +17 -2
- data/lib/belt/cli/deploy_command.rb +9 -0
- data/lib/belt/cli/destroy_command.rb +3 -1
- data/lib/belt/cli/doctor_command.rb +166 -22
- data/lib/belt/cli/generate_command.rb +24 -31
- data/lib/belt/cli/index_command.rb +192 -0
- data/lib/belt/cli/lambda_config_command.rb +2 -1
- data/lib/belt/cli/routes_command/route_inference.rb +4 -3
- data/lib/belt/cli/routes_command.rb +0 -19
- data/lib/belt/cli/views_command.rb +3 -9
- data/lib/belt/cli.rb +1 -0
- data/lib/belt/inflector.rb +8 -0
- data/lib/belt/route_dsl.rb +3 -2
- data/lib/belt/version.rb +1 -1
- data/lib/templates/generate/auth/cognito.tf.erb +11 -0
- data/lib/templates/generate/auth/frontend/ConfirmEmail.jsx +55 -0
- data/lib/templates/generate/auth/frontend/Login.jsx +79 -0
- data/lib/templates/generate/auth/frontend/ProtectedRoute.jsx +9 -0
- data/lib/templates/generate/auth/frontend/SignUp.jsx +58 -0
- data/lib/templates/generate/auth/frontend/apiClient.js +34 -0
- data/lib/templates/generate/auth/frontend/auth.css +157 -0
- data/lib/templates/generate/auth/frontend/auth.js +80 -0
- data/lib/templates/generate/model.rb.erb +4 -6
- data/lib/templates/new_app/config/lambda/api.yml.erb +1 -0
- metadata +37 -1
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
.auth-page {
|
|
2
|
+
--auth-bg: #f6f8fa;
|
|
3
|
+
--auth-card-bg: #ffffff;
|
|
4
|
+
--auth-border: #d0d7de;
|
|
5
|
+
--auth-text: #1f2328;
|
|
6
|
+
--auth-muted: #656d76;
|
|
7
|
+
--auth-input-bg: #f6f8fa;
|
|
8
|
+
--auth-btn: #2da44e;
|
|
9
|
+
--auth-btn-hover: #2c974b;
|
|
10
|
+
--auth-btn-disabled-bg: #94d3a2;
|
|
11
|
+
--auth-btn-disabled-text: #fff;
|
|
12
|
+
--auth-error-bg: rgba(248, 81, 73, 0.08);
|
|
13
|
+
--auth-error-border: rgba(248, 81, 73, 0.4);
|
|
14
|
+
--auth-error-text: #cf222e;
|
|
15
|
+
--auth-link: #0969da;
|
|
16
|
+
--auth-focus: #0969da;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
@media (prefers-color-scheme: dark) {
|
|
20
|
+
.auth-page {
|
|
21
|
+
--auth-bg: #0d1117;
|
|
22
|
+
--auth-card-bg: #161b22;
|
|
23
|
+
--auth-border: #30363d;
|
|
24
|
+
--auth-text: #e6edf3;
|
|
25
|
+
--auth-muted: #8b949e;
|
|
26
|
+
--auth-input-bg: #0d1117;
|
|
27
|
+
--auth-btn: #238636;
|
|
28
|
+
--auth-btn-hover: #2ea043;
|
|
29
|
+
--auth-btn-disabled-bg: #21262d;
|
|
30
|
+
--auth-btn-disabled-text: #484f58;
|
|
31
|
+
--auth-error-bg: rgba(248, 81, 73, 0.1);
|
|
32
|
+
--auth-error-border: rgba(248, 81, 73, 0.4);
|
|
33
|
+
--auth-error-text: #f85149;
|
|
34
|
+
--auth-link: #58a6ff;
|
|
35
|
+
--auth-focus: #58a6ff;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.auth-page {
|
|
40
|
+
min-height: 100vh;
|
|
41
|
+
display: flex;
|
|
42
|
+
align-items: center;
|
|
43
|
+
justify-content: center;
|
|
44
|
+
background: var(--auth-bg);
|
|
45
|
+
padding: 1rem;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.auth-form {
|
|
49
|
+
background: var(--auth-card-bg);
|
|
50
|
+
border: 1px solid var(--auth-border);
|
|
51
|
+
border-radius: 12px;
|
|
52
|
+
padding: 2.5rem;
|
|
53
|
+
width: 100%;
|
|
54
|
+
max-width: 380px;
|
|
55
|
+
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.auth-form h2 {
|
|
59
|
+
color: var(--auth-text);
|
|
60
|
+
font-size: 1.5rem;
|
|
61
|
+
margin: 0 0 0.5rem;
|
|
62
|
+
text-align: center;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.auth-form p {
|
|
66
|
+
color: var(--auth-muted);
|
|
67
|
+
font-size: 0.85rem;
|
|
68
|
+
text-align: center;
|
|
69
|
+
margin: 0 0 1.5rem;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.auth-form input {
|
|
73
|
+
display: block;
|
|
74
|
+
width: 100%;
|
|
75
|
+
padding: 0.75rem 1rem;
|
|
76
|
+
margin-bottom: 0.75rem;
|
|
77
|
+
background: var(--auth-input-bg);
|
|
78
|
+
border: 1px solid var(--auth-border);
|
|
79
|
+
border-radius: 8px;
|
|
80
|
+
color: var(--auth-text);
|
|
81
|
+
font-size: 0.9rem;
|
|
82
|
+
outline: none;
|
|
83
|
+
transition: border-color 0.2s;
|
|
84
|
+
box-sizing: border-box;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.auth-form input:focus {
|
|
88
|
+
border-color: var(--auth-focus);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.auth-form input::placeholder {
|
|
92
|
+
color: var(--auth-muted);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.auth-form button {
|
|
96
|
+
display: block;
|
|
97
|
+
width: 100%;
|
|
98
|
+
padding: 0.75rem;
|
|
99
|
+
margin-top: 0.5rem;
|
|
100
|
+
background: var(--auth-btn);
|
|
101
|
+
border: none;
|
|
102
|
+
border-radius: 8px;
|
|
103
|
+
color: #fff;
|
|
104
|
+
font-size: 0.9rem;
|
|
105
|
+
font-weight: 600;
|
|
106
|
+
cursor: pointer;
|
|
107
|
+
transition: background 0.2s;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.auth-form button:hover {
|
|
111
|
+
background: var(--auth-btn-hover);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.auth-form button:disabled {
|
|
115
|
+
background: var(--auth-btn-disabled-bg);
|
|
116
|
+
color: var(--auth-btn-disabled-text);
|
|
117
|
+
cursor: not-allowed;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.auth-error {
|
|
121
|
+
background: var(--auth-error-bg);
|
|
122
|
+
border: 1px solid var(--auth-error-border);
|
|
123
|
+
border-radius: 8px;
|
|
124
|
+
color: var(--auth-error-text);
|
|
125
|
+
padding: 0.6rem 0.75rem;
|
|
126
|
+
font-size: 0.8rem;
|
|
127
|
+
margin-bottom: 1rem;
|
|
128
|
+
text-align: center;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.auth-link {
|
|
132
|
+
color: var(--auth-muted);
|
|
133
|
+
font-size: 0.8rem;
|
|
134
|
+
text-align: center;
|
|
135
|
+
margin-top: 1.25rem !important;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
.auth-link a {
|
|
139
|
+
color: var(--auth-link);
|
|
140
|
+
text-decoration: none;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
.auth-link a:hover {
|
|
144
|
+
text-decoration: underline;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.auth-btn {
|
|
148
|
+
display: inline-block;
|
|
149
|
+
padding: 0.6rem 1.5rem;
|
|
150
|
+
background: var(--auth-btn);
|
|
151
|
+
border-radius: 8px;
|
|
152
|
+
color: #fff;
|
|
153
|
+
text-decoration: none;
|
|
154
|
+
font-weight: 600;
|
|
155
|
+
font-size: 0.85rem;
|
|
156
|
+
margin-top: 1rem;
|
|
157
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CognitoIdentityProviderClient,
|
|
3
|
+
InitiateAuthCommand,
|
|
4
|
+
RespondToAuthChallengeCommand,
|
|
5
|
+
SignUpCommand,
|
|
6
|
+
ConfirmSignUpCommand
|
|
7
|
+
} from '@aws-sdk/client-cognito-identity-provider'
|
|
8
|
+
|
|
9
|
+
const REGION = import.meta.env.VITE_AWS_REGION
|
|
10
|
+
const CLIENT_ID = import.meta.env.VITE_COGNITO_CLIENT_ID
|
|
11
|
+
|
|
12
|
+
const client = new CognitoIdentityProviderClient({ region: REGION })
|
|
13
|
+
|
|
14
|
+
let idToken = null
|
|
15
|
+
let refreshToken = null
|
|
16
|
+
|
|
17
|
+
export function getToken() { return idToken }
|
|
18
|
+
export function isAuthenticated() { return idToken !== null }
|
|
19
|
+
|
|
20
|
+
export async function signIn(username, password) {
|
|
21
|
+
const response = await client.send(new InitiateAuthCommand({
|
|
22
|
+
AuthFlow: 'USER_PASSWORD_AUTH',
|
|
23
|
+
ClientId: CLIENT_ID,
|
|
24
|
+
AuthParameters: { USERNAME: username, PASSWORD: password }
|
|
25
|
+
}))
|
|
26
|
+
|
|
27
|
+
if (response.ChallengeName === 'NEW_PASSWORD_REQUIRED') {
|
|
28
|
+
return { challenge: 'NEW_PASSWORD_REQUIRED', session: response.Session }
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
setTokens(response.AuthenticationResult)
|
|
32
|
+
return { success: true }
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export async function signUp(email, password) {
|
|
36
|
+
await client.send(new SignUpCommand({
|
|
37
|
+
ClientId: CLIENT_ID,
|
|
38
|
+
Username: email,
|
|
39
|
+
Password: password
|
|
40
|
+
}))
|
|
41
|
+
return { needsConfirmation: true }
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export async function confirmSignUp(email, code) {
|
|
45
|
+
await client.send(new ConfirmSignUpCommand({
|
|
46
|
+
ClientId: CLIENT_ID,
|
|
47
|
+
Username: email,
|
|
48
|
+
ConfirmationCode: code
|
|
49
|
+
}))
|
|
50
|
+
return { success: true }
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export async function completeNewPassword(username, newPassword, session) {
|
|
54
|
+
const response = await client.send(new RespondToAuthChallengeCommand({
|
|
55
|
+
ChallengeName: 'NEW_PASSWORD_REQUIRED',
|
|
56
|
+
ClientId: CLIENT_ID,
|
|
57
|
+
Session: session,
|
|
58
|
+
ChallengeResponses: { USERNAME: username, NEW_PASSWORD: newPassword }
|
|
59
|
+
}))
|
|
60
|
+
setTokens(response.AuthenticationResult)
|
|
61
|
+
return { success: true }
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function signOut() {
|
|
65
|
+
idToken = null
|
|
66
|
+
refreshToken = null
|
|
67
|
+
localStorage.removeItem('idToken')
|
|
68
|
+
localStorage.removeItem('refreshToken')
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function setTokens(authResult) {
|
|
72
|
+
idToken = authResult.IdToken
|
|
73
|
+
refreshToken = authResult.RefreshToken
|
|
74
|
+
localStorage.setItem('idToken', idToken)
|
|
75
|
+
if (refreshToken) localStorage.setItem('refreshToken', refreshToken)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Restore on page load
|
|
79
|
+
const stored = localStorage.getItem('idToken')
|
|
80
|
+
if (stored) idToken = stored
|
|
@@ -4,13 +4,11 @@ class <%= @class_name %> < ApplicationRecord
|
|
|
4
4
|
<% @references.each do |ref| -%>
|
|
5
5
|
belongs_to :<%= ref[:referenced_model] %>
|
|
6
6
|
<% end -%>
|
|
7
|
-
<% if @references.any? &&
|
|
7
|
+
<% if @references.any? && @regular_fields.any? -%>
|
|
8
8
|
|
|
9
9
|
<% end -%>
|
|
10
|
-
<% @
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
<% @regular_fields.each do |field| -%>
|
|
14
|
-
attr_accessor :<%= field[:name] %>
|
|
10
|
+
<% all_accessors = @regular_fields.map { |f| ":#{f[:name]}" } -%>
|
|
11
|
+
<% if all_accessors.any? -%>
|
|
12
|
+
attr_accessor <%= all_accessors.join(', ') %>
|
|
15
13
|
<% end -%>
|
|
16
14
|
end
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
# timeout Lambda timeout in seconds (default: 30)
|
|
6
6
|
# memory_size Lambda memory in MB (default: 256)
|
|
7
7
|
# env_vars Environment variables (static values or ref() for Terraform values)
|
|
8
|
+
# iam_policy_arns Additional IAM policy ARNs to attach (supports ref())
|
|
8
9
|
# dynamodb_tables DynamoDB table access (by name — ARNs built by convention)
|
|
9
10
|
# s3_buckets S3 bucket access declarations
|
|
10
11
|
# sns_triggers SNS topic triggers
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: belt
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.20
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Stowzilla
|
|
@@ -43,6 +43,20 @@ dependencies:
|
|
|
43
43
|
- - ">="
|
|
44
44
|
- !ruby/object:Gem::Version
|
|
45
45
|
version: '7.0'
|
|
46
|
+
- !ruby/object:Gem::Dependency
|
|
47
|
+
name: irb
|
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
|
49
|
+
requirements:
|
|
50
|
+
- - ">="
|
|
51
|
+
- !ruby/object:Gem::Version
|
|
52
|
+
version: '1.0'
|
|
53
|
+
type: :runtime
|
|
54
|
+
prerelease: false
|
|
55
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
56
|
+
requirements:
|
|
57
|
+
- - ">="
|
|
58
|
+
- !ruby/object:Gem::Version
|
|
59
|
+
version: '1.0'
|
|
46
60
|
- !ruby/object:Gem::Dependency
|
|
47
61
|
name: lambda_loadout
|
|
48
62
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -57,6 +71,20 @@ dependencies:
|
|
|
57
71
|
- - "~>"
|
|
58
72
|
- !ruby/object:Gem::Version
|
|
59
73
|
version: '0.0'
|
|
74
|
+
- !ruby/object:Gem::Dependency
|
|
75
|
+
name: rdoc
|
|
76
|
+
requirement: !ruby/object:Gem::Requirement
|
|
77
|
+
requirements:
|
|
78
|
+
- - ">="
|
|
79
|
+
- !ruby/object:Gem::Version
|
|
80
|
+
version: '6.0'
|
|
81
|
+
type: :runtime
|
|
82
|
+
prerelease: false
|
|
83
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
84
|
+
requirements:
|
|
85
|
+
- - ">="
|
|
86
|
+
- !ruby/object:Gem::Version
|
|
87
|
+
version: '6.0'
|
|
60
88
|
description: Belt provides a collection of lightweight utilities for Ruby applications.
|
|
61
89
|
email:
|
|
62
90
|
- andy@stowzilla.com
|
|
@@ -95,6 +123,7 @@ files:
|
|
|
95
123
|
- lib/belt/cli/frontend_setup_command.rb
|
|
96
124
|
- lib/belt/cli/generate_command.rb
|
|
97
125
|
- lib/belt/cli/generator_registry.rb
|
|
126
|
+
- lib/belt/cli/index_command.rb
|
|
98
127
|
- lib/belt/cli/lambda_config_command.rb
|
|
99
128
|
- lib/belt/cli/logs_command.rb
|
|
100
129
|
- lib/belt/cli/new_command.rb
|
|
@@ -144,6 +173,13 @@ files:
|
|
|
144
173
|
- lib/templates/frontend_infra/frontend.tf.erb
|
|
145
174
|
- lib/templates/generate/auth/cognito.tf.erb
|
|
146
175
|
- lib/templates/generate/auth/cognito_outputs.tf.erb
|
|
176
|
+
- lib/templates/generate/auth/frontend/ConfirmEmail.jsx
|
|
177
|
+
- lib/templates/generate/auth/frontend/Login.jsx
|
|
178
|
+
- lib/templates/generate/auth/frontend/ProtectedRoute.jsx
|
|
179
|
+
- lib/templates/generate/auth/frontend/SignUp.jsx
|
|
180
|
+
- lib/templates/generate/auth/frontend/apiClient.js
|
|
181
|
+
- lib/templates/generate/auth/frontend/auth.css
|
|
182
|
+
- lib/templates/generate/auth/frontend/auth.js
|
|
147
183
|
- lib/templates/generate/controller.rb.erb
|
|
148
184
|
- lib/templates/generate/model.rb.erb
|
|
149
185
|
- lib/templates/module/dns.tf.erb
|