descope 1.0.4
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/.github/workflows/ci.yaml +54 -0
- data/.gitignore +59 -0
- data/.release-please-manifest.json +3 -0
- data/.rubocop.yml +10 -0
- data/.rubocop_todo.yml +10 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +90 -0
- data/Gemfile +22 -0
- data/Gemfile.lock +204 -0
- data/LICENSE +21 -0
- data/README.md +1171 -0
- data/Rakefile +31 -0
- data/descope.gemspec +34 -0
- data/examples/ruby/Gemfile +4 -0
- data/examples/ruby/Gemfile.lock +41 -0
- data/examples/ruby/access_key_app.rb +45 -0
- data/examples/ruby/enchantedlink_app.rb +65 -0
- data/examples/ruby/magiclink_app.rb +81 -0
- data/examples/ruby/management/Gemfile +5 -0
- data/examples/ruby/management/Gemfile.lock +38 -0
- data/examples/ruby/management/access_key_app.rb +71 -0
- data/examples/ruby/management/audit_app.rb +25 -0
- data/examples/ruby/management/authz_app.rb +135 -0
- data/examples/ruby/management/authz_files.json +229 -0
- data/examples/ruby/management/flow_app.rb +57 -0
- data/examples/ruby/management/permission_app.rb +56 -0
- data/examples/ruby/management/role_app.rb +58 -0
- data/examples/ruby/management/tenant_app.rb +60 -0
- data/examples/ruby/management/user_app.rb +60 -0
- data/examples/ruby/oauth_app.rb +39 -0
- data/examples/ruby/otp_app.rb +50 -0
- data/examples/ruby/password_app.rb +76 -0
- data/examples/ruby/saml_app.rb +38 -0
- data/examples/ruby-on-rails-api/descope/.dockerignore +37 -0
- data/examples/ruby-on-rails-api/descope/.gitattributes +9 -0
- data/examples/ruby-on-rails-api/descope/.gitignore +40 -0
- data/examples/ruby-on-rails-api/descope/.node-version +1 -0
- data/examples/ruby-on-rails-api/descope/.ruby-version +1 -0
- data/examples/ruby-on-rails-api/descope/Dockerfile +75 -0
- data/examples/ruby-on-rails-api/descope/Gemfile +67 -0
- data/examples/ruby-on-rails-api/descope/Gemfile.lock +284 -0
- data/examples/ruby-on-rails-api/descope/Procfile.dev +3 -0
- data/examples/ruby-on-rails-api/descope/README.md +54 -0
- data/examples/ruby-on-rails-api/descope/Rakefile +6 -0
- data/examples/ruby-on-rails-api/descope/app/assets/builds/.keep +0 -0
- data/examples/ruby-on-rails-api/descope/app/assets/config/manifest.js +3 -0
- data/examples/ruby-on-rails-api/descope/app/assets/images/.keep +0 -0
- data/examples/ruby-on-rails-api/descope/app/assets/images/descope.jpeg +0 -0
- data/examples/ruby-on-rails-api/descope/app/assets/images/favicon.ico +0 -0
- data/examples/ruby-on-rails-api/descope/app/assets/images/logo192.png +0 -0
- data/examples/ruby-on-rails-api/descope/app/assets/images/logo512.png +0 -0
- data/examples/ruby-on-rails-api/descope/app/assets/stylesheets/application.bootstrap.scss +67 -0
- data/examples/ruby-on-rails-api/descope/app/channels/application_cable/channel.rb +4 -0
- data/examples/ruby-on-rails-api/descope/app/channels/application_cable/connection.rb +4 -0
- data/examples/ruby-on-rails-api/descope/app/controllers/application_controller.rb +2 -0
- data/examples/ruby-on-rails-api/descope/app/controllers/concerns/.keep +0 -0
- data/examples/ruby-on-rails-api/descope/app/controllers/homepage_controller.rb +4 -0
- data/examples/ruby-on-rails-api/descope/app/controllers/session_controller.rb +66 -0
- data/examples/ruby-on-rails-api/descope/app/helpers/application_helper.rb +2 -0
- data/examples/ruby-on-rails-api/descope/app/helpers/homepage_helper.rb +2 -0
- data/examples/ruby-on-rails-api/descope/app/helpers/session_helper.rb +2 -0
- data/examples/ruby-on-rails-api/descope/app/javascript/App.css +53 -0
- data/examples/ruby-on-rails-api/descope/app/javascript/application.js +5 -0
- data/examples/ruby-on-rails-api/descope/app/javascript/components/App.jsx +4 -0
- data/examples/ruby-on-rails-api/descope/app/javascript/components/Dashboard.jsx +60 -0
- data/examples/ruby-on-rails-api/descope/app/javascript/components/Home.jsx +27 -0
- data/examples/ruby-on-rails-api/descope/app/javascript/components/Login.jsx +45 -0
- data/examples/ruby-on-rails-api/descope/app/javascript/components/Profile.jsx +81 -0
- data/examples/ruby-on-rails-api/descope/app/javascript/components/index.html +11 -0
- data/examples/ruby-on-rails-api/descope/app/javascript/components/index.jsx +24 -0
- data/examples/ruby-on-rails-api/descope/app/javascript/controllers/application.js +9 -0
- data/examples/ruby-on-rails-api/descope/app/javascript/controllers/index.js +5 -0
- data/examples/ruby-on-rails-api/descope/app/javascript/reportWebVitals.js +13 -0
- data/examples/ruby-on-rails-api/descope/app/javascript/routes/index.jsx +17 -0
- data/examples/ruby-on-rails-api/descope/app/jobs/application_job.rb +7 -0
- data/examples/ruby-on-rails-api/descope/app/mailers/application_mailer.rb +4 -0
- data/examples/ruby-on-rails-api/descope/app/models/application_record.rb +3 -0
- data/examples/ruby-on-rails-api/descope/app/models/concerns/.keep +0 -0
- data/examples/ruby-on-rails-api/descope/app/views/homepage/index.html.erb +2 -0
- data/examples/ruby-on-rails-api/descope/app/views/layouts/application.html.erb +16 -0
- data/examples/ruby-on-rails-api/descope/app/views/layouts/mailer.html.erb +13 -0
- data/examples/ruby-on-rails-api/descope/app/views/layouts/mailer.text.erb +1 -0
- data/examples/ruby-on-rails-api/descope/app/views/session/index.html.erb +2 -0
- data/examples/ruby-on-rails-api/descope/bin/bundle +109 -0
- data/examples/ruby-on-rails-api/descope/bin/dev +11 -0
- data/examples/ruby-on-rails-api/descope/bin/docker-entrypoint +8 -0
- data/examples/ruby-on-rails-api/descope/bin/rails +4 -0
- data/examples/ruby-on-rails-api/descope/bin/rake +4 -0
- data/examples/ruby-on-rails-api/descope/bin/setup +36 -0
- data/examples/ruby-on-rails-api/descope/build.js +30 -0
- data/examples/ruby-on-rails-api/descope/config/application.rb +42 -0
- data/examples/ruby-on-rails-api/descope/config/boot.rb +4 -0
- data/examples/ruby-on-rails-api/descope/config/cable.yml +10 -0
- data/examples/ruby-on-rails-api/descope/config/config.yml +9 -0
- data/examples/ruby-on-rails-api/descope/config/credentials.yml.enc +1 -0
- data/examples/ruby-on-rails-api/descope/config/database.yml +25 -0
- data/examples/ruby-on-rails-api/descope/config/environment.rb +5 -0
- data/examples/ruby-on-rails-api/descope/config/environments/development.rb +76 -0
- data/examples/ruby-on-rails-api/descope/config/environments/production.rb +97 -0
- data/examples/ruby-on-rails-api/descope/config/environments/test.rb +64 -0
- data/examples/ruby-on-rails-api/descope/config/initializers/assets.rb +13 -0
- data/examples/ruby-on-rails-api/descope/config/initializers/content_security_policy.rb +25 -0
- data/examples/ruby-on-rails-api/descope/config/initializers/filter_parameter_logging.rb +8 -0
- data/examples/ruby-on-rails-api/descope/config/initializers/inflections.rb +16 -0
- data/examples/ruby-on-rails-api/descope/config/initializers/load_config.rb +12 -0
- data/examples/ruby-on-rails-api/descope/config/initializers/permissions_policy.rb +13 -0
- data/examples/ruby-on-rails-api/descope/config/locales/en.yml +31 -0
- data/examples/ruby-on-rails-api/descope/config/puma.rb +35 -0
- data/examples/ruby-on-rails-api/descope/config/routes.rb +18 -0
- data/examples/ruby-on-rails-api/descope/config/storage.yml +34 -0
- data/examples/ruby-on-rails-api/descope/config.ru +6 -0
- data/examples/ruby-on-rails-api/descope/db/seeds.rb +9 -0
- data/examples/ruby-on-rails-api/descope/lib/assets/.keep +0 -0
- data/examples/ruby-on-rails-api/descope/lib/tasks/.keep +0 -0
- data/examples/ruby-on-rails-api/descope/log/.keep +0 -0
- data/examples/ruby-on-rails-api/descope/package-lock.json +19680 -0
- data/examples/ruby-on-rails-api/descope/package.json +51 -0
- data/examples/ruby-on-rails-api/descope/public/404.html +67 -0
- data/examples/ruby-on-rails-api/descope/public/422.html +67 -0
- data/examples/ruby-on-rails-api/descope/public/500.html +66 -0
- data/examples/ruby-on-rails-api/descope/public/apple-touch-icon-precomposed.png +0 -0
- data/examples/ruby-on-rails-api/descope/public/apple-touch-icon.png +0 -0
- data/examples/ruby-on-rails-api/descope/public/favicon.ico +0 -0
- data/examples/ruby-on-rails-api/descope/public/robots.txt +1 -0
- data/examples/ruby-on-rails-api/descope/storage/.keep +0 -0
- data/examples/ruby-on-rails-api/descope/tmp/.keep +0 -0
- data/examples/ruby-on-rails-api/descope/tmp/pids/.keep +0 -0
- data/examples/ruby-on-rails-api/descope/tmp/storage/.keep +0 -0
- data/examples/ruby-on-rails-api/descope/vendor/.keep +0 -0
- data/examples/ruby-on-rails-api/descope/yarn.lock +10780 -0
- data/lib/descope/api/v1/auth/enchantedlink.rb +156 -0
- data/lib/descope/api/v1/auth/magiclink.rb +170 -0
- data/lib/descope/api/v1/auth/oauth.rb +72 -0
- data/lib/descope/api/v1/auth/otp.rb +186 -0
- data/lib/descope/api/v1/auth/password.rb +100 -0
- data/lib/descope/api/v1/auth/saml.rb +48 -0
- data/lib/descope/api/v1/auth/totp.rb +72 -0
- data/lib/descope/api/v1/auth.rb +452 -0
- data/lib/descope/api/v1/management/access_key.rb +81 -0
- data/lib/descope/api/v1/management/audit.rb +82 -0
- data/lib/descope/api/v1/management/authz.rb +165 -0
- data/lib/descope/api/v1/management/common.rb +147 -0
- data/lib/descope/api/v1/management/flow.rb +55 -0
- data/lib/descope/api/v1/management/password.rb +58 -0
- data/lib/descope/api/v1/management/permission.rb +48 -0
- data/lib/descope/api/v1/management/project.rb +53 -0
- data/lib/descope/api/v1/management/role.rb +48 -0
- data/lib/descope/api/v1/management/scim.rb +206 -0
- data/lib/descope/api/v1/management/sso_settings.rb +153 -0
- data/lib/descope/api/v1/management/tenant.rb +71 -0
- data/lib/descope/api/v1/management/user.rb +619 -0
- data/lib/descope/api/v1/management.rb +38 -0
- data/lib/descope/api/v1/session.rb +84 -0
- data/lib/descope/api/v1.rb +13 -0
- data/lib/descope/client.rb +6 -0
- data/lib/descope/exception.rb +50 -0
- data/lib/descope/mixins/common.rb +129 -0
- data/lib/descope/mixins/headers.rb +15 -0
- data/lib/descope/mixins/http.rb +133 -0
- data/lib/descope/mixins/initializer.rb +80 -0
- data/lib/descope/mixins/logging.rb +30 -0
- data/lib/descope/mixins/validation.rb +79 -0
- data/lib/descope/mixins.rb +22 -0
- data/lib/descope/version.rb +7 -0
- data/lib/descope.rb +9 -0
- data/lib/descope_client.rb +5 -0
- data/release-please-config.json +18 -0
- data/renovate.json +6 -0
- data/spec/factories/user.rb +16 -0
- data/spec/lib.descope/api/v1/auth/enchantedlink_spec.rb +159 -0
- data/spec/lib.descope/api/v1/auth/magiclink_spec.rb +282 -0
- data/spec/lib.descope/api/v1/auth/oauth_spec.rb +117 -0
- data/spec/lib.descope/api/v1/auth/otp_spec.rb +285 -0
- data/spec/lib.descope/api/v1/auth/password_spec.rb +124 -0
- data/spec/lib.descope/api/v1/auth/saml_spec.rb +55 -0
- data/spec/lib.descope/api/v1/auth/totp_spec.rb +70 -0
- data/spec/lib.descope/api/v1/auth_spec.rb +372 -0
- data/spec/lib.descope/api/v1/management/access_key_spec.rb +118 -0
- data/spec/lib.descope/api/v1/management/audit_spec.rb +78 -0
- data/spec/lib.descope/api/v1/management/authz_spec.rb +336 -0
- data/spec/lib.descope/api/v1/management/flow_spec.rb +78 -0
- data/spec/lib.descope/api/v1/management/password_spec.rb +25 -0
- data/spec/lib.descope/api/v1/management/permission_spec.rb +81 -0
- data/spec/lib.descope/api/v1/management/project_spec.rb +63 -0
- data/spec/lib.descope/api/v1/management/role_spec.rb +85 -0
- data/spec/lib.descope/api/v1/management/scim_spec.rb +312 -0
- data/spec/lib.descope/api/v1/management/sso_settings_spec.rb +172 -0
- data/spec/lib.descope/api/v1/management/tenant_spec.rb +141 -0
- data/spec/lib.descope/api/v1/management/user_spec.rb +667 -0
- data/spec/lib.descope/api/v1/session_spec.rb +117 -0
- data/spec/lib.descope/client_spec.rb +40 -0
- data/spec/spec_helper.rb +72 -0
- data/spec/support/client_config.rb +14 -0
- data/spec/support/dummy_class.rb +36 -0
- data/spec/support/utils.rb +32 -0
- metadata +420 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
@import 'bootstrap/scss/bootstrap';
|
|
2
|
+
@import 'bootstrap-icons/font/bootstrap-icons';
|
|
3
|
+
|
|
4
|
+
@import url('https://fonts.googleapis.com/css2?family=Golos+Text:wght@500&display=swap');
|
|
5
|
+
|
|
6
|
+
.page {
|
|
7
|
+
display: flex;
|
|
8
|
+
flex-direction: column;
|
|
9
|
+
align-items: center;
|
|
10
|
+
justify-content: center;
|
|
11
|
+
margin-bottom: 5vh;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.title {
|
|
15
|
+
margin-top: 10vh;
|
|
16
|
+
margin-bottom: 5vh;
|
|
17
|
+
font-size: 2em;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.link {
|
|
21
|
+
text-decoration: none;
|
|
22
|
+
margin-bottom: 5vh;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.btn {
|
|
26
|
+
border: None;
|
|
27
|
+
background-color: #00BD67;
|
|
28
|
+
padding: 15px 25px;
|
|
29
|
+
color: #fff;
|
|
30
|
+
font-size: 1.1em;
|
|
31
|
+
border-radius: 9px;
|
|
32
|
+
margin-top: 12px;
|
|
33
|
+
margin-right: 1vh;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.btn:hover, .btn:focus, .btn:active, .btn.active, .open>.dropdown-toggle.btn {
|
|
37
|
+
color: #fff;
|
|
38
|
+
background-color: #00b3db;
|
|
39
|
+
border-color: #285e8e; /*set the color you want here*/
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.student {
|
|
43
|
+
margin-bottom: 5vh;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.students {
|
|
47
|
+
font-size: 1.5em;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
body {
|
|
51
|
+
margin: 0;
|
|
52
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
|
53
|
+
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
|
54
|
+
sans-serif;
|
|
55
|
+
-webkit-font-smoothing: antialiased;
|
|
56
|
+
-moz-osx-font-smoothing: grayscale;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
code {
|
|
60
|
+
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
|
61
|
+
monospace;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.logout {
|
|
65
|
+
position: relative;
|
|
66
|
+
top: -22px;
|
|
67
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'descope'
|
|
4
|
+
|
|
5
|
+
class SessionController < ApplicationController
|
|
6
|
+
attr_reader :jwt_response
|
|
7
|
+
|
|
8
|
+
before_action :authenticate_request
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def get_roles
|
|
12
|
+
puts '🔐 Getting roles...'
|
|
13
|
+
if @jwt_response['roles'].nil? || @jwt_response['roles'].empty?
|
|
14
|
+
puts '🔐 Empty roles! You are not a trained Descope user!'
|
|
15
|
+
return render json: { secretMessage: 'Empty roles! You are now a trained Descope user!', roles: [] }
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
roles = @jwt_response['roles']
|
|
19
|
+
puts "🔐 Got Roles: #{roles}"
|
|
20
|
+
render json: { secretMessage: 'You are now a trained Descope user!', roles: }
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def get_role_data
|
|
24
|
+
valid_student_role = descope_client.validate_roles(
|
|
25
|
+
jwt_response: @jwt_response, roles: ['student']
|
|
26
|
+
)
|
|
27
|
+
valid_teacher_role = descope_client.validate_roles(
|
|
28
|
+
jwt_response: @jwt_response, roles: ['teacher']
|
|
29
|
+
)
|
|
30
|
+
if valid_student_role && valid_teacher_role
|
|
31
|
+
render json: { valid_teacher: valid_teacher_role, valid_student: valid_student_role }
|
|
32
|
+
else
|
|
33
|
+
render json: { valid_teacher: 'no valid teacher role found', valid_student: 'no valid student role found' }
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
private
|
|
38
|
+
|
|
39
|
+
def authenticate_request
|
|
40
|
+
puts '🔐 Authenticating request...'
|
|
41
|
+
unless request.headers['Authorization'].nil? # check if token is present in the request header
|
|
42
|
+
auth_request = request.headers['Authorization']
|
|
43
|
+
session_token = auth_request&.remove('Bearer ')
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
return render json: { error: '❌ Invalid session token!' }, status: :unauthorized unless session_token
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
begin
|
|
50
|
+
@jwt_response = descope_client.validate_session(session_token:)
|
|
51
|
+
rescue Descope::AuthException
|
|
52
|
+
return render json: { error: '❌ Invalid session token!' }, status: :unauthorized
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
logger.info "🔐 Authenticated successfully! token validated: #{@jwt_response}"
|
|
56
|
+
@jwt_response
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def descope_client
|
|
60
|
+
@descope_client ||= Descope::Client.new({ project_id: APP_CONFIG['react_app_project_id'], log_level: APP_CONFIG['ruby_sdk_log_level'] })
|
|
61
|
+
rescue Descope::AuthException => e
|
|
62
|
+
logger.error "Failed to initialize descope sdk: #{e.message}"
|
|
63
|
+
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
@import url('https://fonts.googleapis.com/css2?family=Golos+Text:wght@500&display=swap');
|
|
2
|
+
|
|
3
|
+
.page {
|
|
4
|
+
display: flex;
|
|
5
|
+
flex-direction: column;
|
|
6
|
+
align-items: center;
|
|
7
|
+
justify-content: center;
|
|
8
|
+
margin-bottom: 5vh;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.title {
|
|
12
|
+
margin-top: 10vh;
|
|
13
|
+
margin-bottom: 5vh;
|
|
14
|
+
font-size: 2em;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.link {
|
|
18
|
+
text-decoration: none;
|
|
19
|
+
margin-bottom: 5vh;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.btn {
|
|
23
|
+
border: None;
|
|
24
|
+
background-color: #00BD67;
|
|
25
|
+
padding: 15px 25px;
|
|
26
|
+
color: #fff;
|
|
27
|
+
font-size: 1.1em;
|
|
28
|
+
border-radius: 9px;
|
|
29
|
+
margin-top: 12px;
|
|
30
|
+
margin-right: 1vh;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.student {
|
|
34
|
+
margin-bottom: 5vh;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.students {
|
|
38
|
+
font-size: 1.5em;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
body {
|
|
42
|
+
margin: 0;
|
|
43
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
|
44
|
+
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
|
45
|
+
sans-serif;
|
|
46
|
+
-webkit-font-smoothing: antialiased;
|
|
47
|
+
-moz-osx-font-smoothing: grayscale;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
code {
|
|
51
|
+
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
|
52
|
+
monospace;
|
|
53
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { useEffect, useState } from "react";
|
|
3
|
+
import { Link } from "react-router-dom";
|
|
4
|
+
import { useNavigate } from "react-router-dom";
|
|
5
|
+
import { getSessionToken } from '@descope/react-sdk';
|
|
6
|
+
import '../App.css';
|
|
7
|
+
|
|
8
|
+
function Dashboard() {
|
|
9
|
+
const sessionToken = getSessionToken(); // get the session token
|
|
10
|
+
const navigate = useNavigate()
|
|
11
|
+
const [roles, setRoles] = useState({
|
|
12
|
+
teacherRole: false,
|
|
13
|
+
studentRole: false
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
fetch('/get_role_data', { // call the api endpoint from the flask server
|
|
18
|
+
headers: {
|
|
19
|
+
Accept: 'application/json',
|
|
20
|
+
Authorization: 'Bearer ' + sessionToken,
|
|
21
|
+
}
|
|
22
|
+
}).then(data => {
|
|
23
|
+
if (data.status === 401) {
|
|
24
|
+
navigate('/login')
|
|
25
|
+
}
|
|
26
|
+
return data.json()
|
|
27
|
+
}).then(jsonData => {
|
|
28
|
+
setRoles({
|
|
29
|
+
teacherRole: jsonData.valid_teacher,
|
|
30
|
+
studentRole: jsonData.valid_student
|
|
31
|
+
})
|
|
32
|
+
}).catch((err) => {
|
|
33
|
+
console.log(err)
|
|
34
|
+
navigate('/login')
|
|
35
|
+
})
|
|
36
|
+
}, [])
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<div className='page'>
|
|
40
|
+
<h1 className='title'>Dashboard</h1>
|
|
41
|
+
<Link className='link btn' to="/profile">Profile</Link>
|
|
42
|
+
{roles.teacherRole && (
|
|
43
|
+
<div className='page'>
|
|
44
|
+
<h1>Welcome back Teacher!</h1>
|
|
45
|
+
<p className='students'>You have 50+ students currently 🧑🎓</p>
|
|
46
|
+
</div>
|
|
47
|
+
)}
|
|
48
|
+
{roles.studentRole && (
|
|
49
|
+
<div className='page'>
|
|
50
|
+
<h1>Welcome back Student!</h1>
|
|
51
|
+
<p className='student'>Unlucky! You have homework!</p>
|
|
52
|
+
<iframe src="https://giphy.com/embed/H9UeFGxZz4cBG" width="469" height="480" allowFullScreen></iframe>
|
|
53
|
+
</div>
|
|
54
|
+
)}
|
|
55
|
+
</div>
|
|
56
|
+
)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
export default Dashboard;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import '../App.css';
|
|
2
|
+
import { useEffect } from "react";
|
|
3
|
+
import { Link } from "react-router-dom";
|
|
4
|
+
import { useSession } from '@descope/react-sdk'
|
|
5
|
+
import { useNavigate } from "react-router-dom";
|
|
6
|
+
import React from "react";
|
|
7
|
+
|
|
8
|
+
function Home() {
|
|
9
|
+
const { isAuthenticated } = useSession()
|
|
10
|
+
const navigate = useNavigate()
|
|
11
|
+
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
if (isAuthenticated) {
|
|
14
|
+
return navigate("/profile");
|
|
15
|
+
}
|
|
16
|
+
}, [isAuthenticated]) // listen for when isAuthenticated has changed
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<div className='page'>
|
|
20
|
+
<h1 className='title'>Descope - Ruby On Rails Example App</h1>
|
|
21
|
+
<Link className='link btn' to="/login">Login</Link>
|
|
22
|
+
<iframe src="https://giphy.com/embed/bKj0qEKTVBdF2o5Dgn" width="480" height="352" allowFullScreen></iframe>
|
|
23
|
+
</div>
|
|
24
|
+
)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export default Home;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import '../App.css';
|
|
2
|
+
import React, { useEffect } from "react";
|
|
3
|
+
import { Descope, useSession, useUser } from '@descope/react-sdk'
|
|
4
|
+
import { useNavigate } from "react-router-dom";
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
function Login() {
|
|
8
|
+
// isAuthenticated: boolean - is the user authenticated?
|
|
9
|
+
// isSessionLoading: boolean - Use this for showing loading screens while objects are being loaded
|
|
10
|
+
const { isAuthenticated, isSessionLoading } = useSession()
|
|
11
|
+
// isUserLoading: boolean - Use this for showing loading screens while objects are being loaded
|
|
12
|
+
const { isUserLoading } = useUser()
|
|
13
|
+
const navigate = useNavigate()
|
|
14
|
+
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
if (isAuthenticated) {
|
|
17
|
+
return navigate("/profile");
|
|
18
|
+
}
|
|
19
|
+
}, [isAuthenticated]) // listen for when isAuthenticated has changed
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<div className='page'>
|
|
23
|
+
{
|
|
24
|
+
(isSessionLoading || isUserLoading) && <p>Loading...</p>
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
{!isAuthenticated &&
|
|
28
|
+
(
|
|
29
|
+
<>
|
|
30
|
+
<h1 className='title'>Login/SignUp to see the Secret Message!</h1>
|
|
31
|
+
<Descope
|
|
32
|
+
flowId="sign-up-or-in"
|
|
33
|
+
onSuccess = {(e) => console.log(e.detail.user)}
|
|
34
|
+
onError={(e) => console.log('Could not log in! ' + e.detail.error)}
|
|
35
|
+
theme="light"
|
|
36
|
+
/>
|
|
37
|
+
</>
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
</div>
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
export default Login;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { useState, useEffect, useCallback } from "react";
|
|
3
|
+
import { useDescope, useUser, getSessionToken, useSession } from '@descope/react-sdk'
|
|
4
|
+
import { useNavigate } from "react-router-dom";
|
|
5
|
+
import { Link } from "react-router-dom";
|
|
6
|
+
import '../App.css';
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
function Profile() {
|
|
10
|
+
const { isSessionLoading } = useSession()
|
|
11
|
+
|
|
12
|
+
const { user } = useUser()
|
|
13
|
+
const { logout } = useDescope()
|
|
14
|
+
const navigate = useNavigate()
|
|
15
|
+
|
|
16
|
+
const [secret, setSecret] = useState({
|
|
17
|
+
secret: "",
|
|
18
|
+
roles: []
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
const sessionToken = getSessionToken(); // get the session token
|
|
22
|
+
|
|
23
|
+
const logoutUser = useCallback(async () => {
|
|
24
|
+
await logout()
|
|
25
|
+
return navigate('/login')
|
|
26
|
+
}, [logout, navigate]);
|
|
27
|
+
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
fetch('/get_roles', { // call the api endpoint from the flask server
|
|
30
|
+
headers: {
|
|
31
|
+
Accept: 'application/json',
|
|
32
|
+
Authorization: 'Bearer ' + sessionToken,
|
|
33
|
+
}
|
|
34
|
+
}).then(res => {
|
|
35
|
+
if (!res.ok) {
|
|
36
|
+
throw Error(res.statusText);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (res.status === 401) {
|
|
40
|
+
navigate('/login')
|
|
41
|
+
}
|
|
42
|
+
return res.json()
|
|
43
|
+
}).then(jsonData => {
|
|
44
|
+
setSecret({
|
|
45
|
+
secret: jsonData.secretMessage,
|
|
46
|
+
roles: jsonData.roles
|
|
47
|
+
})
|
|
48
|
+
}).catch((err) => {
|
|
49
|
+
console.log(err)
|
|
50
|
+
navigate('/login')
|
|
51
|
+
})
|
|
52
|
+
}, [])
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<>
|
|
56
|
+
{user && (
|
|
57
|
+
<div className='page profile'>
|
|
58
|
+
<div>
|
|
59
|
+
<h1 className='title'>Hello {user.name} 👋</h1>
|
|
60
|
+
<div>My Private Component</div>
|
|
61
|
+
<p>Secret Message: <span style={{ padding: "5px 10px", color: "white", backgroundColor: "black" }}>{secret.secret}</span></p>
|
|
62
|
+
<p>Your Role(s): </p>
|
|
63
|
+
{!secret.roles || secret.roles.length === 0 ?
|
|
64
|
+
<p><span style={{ color: "green", fontWeight: "bold"}}>No role found!</span></p>
|
|
65
|
+
:
|
|
66
|
+
secret.roles.map((role, i) => (
|
|
67
|
+
<p key={i}><span style={{ color: "green", fontWeight: "bold" }}>{role}</span></p>
|
|
68
|
+
))
|
|
69
|
+
}
|
|
70
|
+
<Link className='link btn' to="/">Home</Link>
|
|
71
|
+
<Link className='link btn' to="/dashboard">Dashboard</Link>
|
|
72
|
+
<button className='btn logout' onClick={logoutUser}>Logout</button>
|
|
73
|
+
</div>
|
|
74
|
+
</div>
|
|
75
|
+
)}
|
|
76
|
+
</>
|
|
77
|
+
)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
export default Profile;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title>Descope React demo app</title>
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
+
</head>
|
|
7
|
+
<body>
|
|
8
|
+
<div id="root"></div>
|
|
9
|
+
<script type="module" src="./index.jsx"></script>
|
|
10
|
+
</body>
|
|
11
|
+
</html>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import ReactDOM from 'react-dom/client';
|
|
3
|
+
import App from "./App";
|
|
4
|
+
import reportWebVitals from '../reportWebVitals';
|
|
5
|
+
import { AuthProvider } from '@descope/react-sdk'
|
|
6
|
+
import '../App.css';
|
|
7
|
+
|
|
8
|
+
document.addEventListener("turbo:load", () => {
|
|
9
|
+
document.body.innerHTML = '<div id="root"></div>';
|
|
10
|
+
const root = ReactDOM.createRoot(document.getElementById("root"));
|
|
11
|
+
|
|
12
|
+
root.render(
|
|
13
|
+
<React.StrictMode>
|
|
14
|
+
<AuthProvider projectId={process.env.REACT_APP_PROJECT_ID}>
|
|
15
|
+
<App />
|
|
16
|
+
</AuthProvider>
|
|
17
|
+
</React.StrictMode>
|
|
18
|
+
);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
// If you want to start measuring performance in your app, pass a function
|
|
22
|
+
// to log results (for example: reportWebVitals(console.log))
|
|
23
|
+
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
|
|
24
|
+
reportWebVitals();
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const reportWebVitals = onPerfEntry => {
|
|
2
|
+
if (onPerfEntry && onPerfEntry instanceof Function) {
|
|
3
|
+
import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
|
|
4
|
+
getCLS(onPerfEntry);
|
|
5
|
+
getFID(onPerfEntry);
|
|
6
|
+
getFCP(onPerfEntry);
|
|
7
|
+
getLCP(onPerfEntry);
|
|
8
|
+
getTTFB(onPerfEntry);
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export default reportWebVitals;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
|
|
3
|
+
import Home from "../components/Home";
|
|
4
|
+
import Login from "../components/Login";
|
|
5
|
+
import Profile from "../components/Profile";
|
|
6
|
+
import Dashboard from "../components/Dashboard";
|
|
7
|
+
|
|
8
|
+
export default (
|
|
9
|
+
<Router>
|
|
10
|
+
<Routes>
|
|
11
|
+
<Route path="/" element={<Home />} />
|
|
12
|
+
<Route path='/login' element={<Login />} />
|
|
13
|
+
<Route path='/profile' element={<Profile />} />
|
|
14
|
+
<Route path='/dashboard' element={<Dashboard />} />
|
|
15
|
+
</Routes>
|
|
16
|
+
</Router>
|
|
17
|
+
);
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
class ApplicationJob < ActiveJob::Base
|
|
2
|
+
# Automatically retry jobs that encountered a deadlock
|
|
3
|
+
# retry_on ActiveRecord::Deadlocked
|
|
4
|
+
|
|
5
|
+
# Most jobs are safe to ignore if the underlying records are no longer available
|
|
6
|
+
# discard_on ActiveJob::DeserializationError
|
|
7
|
+
end
|
|
File without changes
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title>RailsDescope</title>
|
|
5
|
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
6
|
+
<%= csrf_meta_tags %>
|
|
7
|
+
<%= csp_meta_tag %>
|
|
8
|
+
|
|
9
|
+
<%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
|
|
10
|
+
<%= javascript_include_tag "application", "data-turbo-track": "reload", type: "module" %>
|
|
11
|
+
</head>
|
|
12
|
+
|
|
13
|
+
<body>
|
|
14
|
+
<%= yield %>
|
|
15
|
+
</body>
|
|
16
|
+
</html>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<%= yield %>
|