Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

27 confirm email address after registration #46

Merged
merged 40 commits into from
Feb 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
2ddd41a
WIP
tbsvttr Jan 31, 2023
709711e
Add validation for confirmation, override Devise controllers, add specs
JustLime Feb 1, 2023
0e0ce00
Add confirmation for created User in SPA system specs
JustLime Feb 1, 2023
59fc195
Fix specs with missing email confirmation
JustLime Feb 2, 2023
ee305b6
Add system spec for registering and confirming new user
JustLime Feb 2, 2023
f489c14
Refactor registrations_controller_spec.rb
JustLime Feb 2, 2023
f84f775
Add specs for Users::ConfirmationsController
JustLime Feb 2, 2023
c4db6ac
Add specs for User model
JustLime Feb 2, 2023
6146388
WIP
JustLime Feb 2, 2023
cfac2a9
Move confirmation of User in system spec into factory
JustLime Feb 6, 2023
72d2ce7
Remove unnecessary code in registrations_controller.rb
JustLime Feb 6, 2023
6595404
Move comment to right place
JustLime Feb 6, 2023
16c6493
Add spec to check if time is in period
JustLime Feb 6, 2023
131b71e
Move one line method to endless style
JustLime Feb 6, 2023
118cc89
Change User.first with memoized helper
JustLime Feb 6, 2023
5b8c299
Fix routing
JustLime Feb 6, 2023
f66d3b7
Add confirmed User to factory
JustLime Feb 6, 2023
03d0114
Set confirmation period back to 3 days
JustLime Feb 6, 2023
bf85cd1
Replace text for notification
JustLime Feb 6, 2023
4f6d4ef
Enforce types for React JSX components
JustLime Feb 7, 2023
237532d
Fix bug where tracking item selection did not work
JustLime Feb 7, 2023
ec17c94
Make env variables more consistent
JustLime Feb 7, 2023
541c21b
Change env values, also change Devise config and add routes plus specs
JustLime Feb 8, 2023
1326e71
Overwrite Devise controller and mailer view
JustLime Feb 8, 2023
0042c5b
Add password reset and password change screen
JustLime Feb 8, 2023
d30afa6
Add env for password reset mail view
JustLime Feb 9, 2023
b0b3c77
Add specs for Users::PasswordsController
JustLime Feb 9, 2023
54bf4a0
Remove forced layout in forms, also add notification for password reset
JustLime Feb 9, 2023
5b4e274
Add specs for password reset and entering new password
JustLime Feb 9, 2023
4f38871
Add more specs for password reset and entering new password
JustLime Feb 9, 2023
53b93ec
Add spec for Users::PasswordsController
JustLime Feb 9, 2023
1d57882
Fix env variables
JustLime Feb 9, 2023
ae50a49
Add waiting time preventing Capybara to click too fast
JustLime Feb 9, 2023
cb739fb
Add button to go back to root page
JustLime Feb 9, 2023
414098c
Replace ifElse with switch-case, move logic to function
JustLime Feb 9, 2023
3b357be
Add error message to redirect url in Users::ConfirmationsController
JustLime Feb 9, 2023
789b700
Move onClick to own function, refactor and make code consistent
JustLime Feb 9, 2023
0241e25
Add dynamic error message of email confirmation as query parameter
JustLime Feb 9, 2023
faef0c7
Refactor functions, move dependency in package.json
JustLime Feb 9, 2023
166589f
Add spec for successful password change in Users::PasswordsController
JustLime Feb 9, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .env.development
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
SWAGGER_UI = "http://localhost:3000/"
APP_HOST=localhost
APP_PORT=3000
1 change: 1 addition & 0 deletions .env.production
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# TODO: Find values!
4 changes: 2 additions & 2 deletions .env.test
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
SWAGGER_UI = "http://localhost:3000/"
HOST_URI = "www.example.com"
APP_HOST=localhost
APP_PORT=3000
24 changes: 24 additions & 0 deletions app/controllers/users/confirmations_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# frozen_string_literal: true

class Users::ConfirmationsController < Devise::ConfirmationsController
# GET /resource/confirmation?confirmation_token=abcdef
def show
self.resource = resource_class.confirm_by_token(params[:confirmation_token])

if resource.errors.empty?
redirect_to "/spa/confirmation_successful"
else
redirect_to "/spa/confirmation_error?#{model_name}=#{error_type}", allow_other_host: true
end
end

private

def model_name
resource.errors.first.attribute.to_s
end

def error_type
resource.errors.first.type.to_s
end
end
26 changes: 26 additions & 0 deletions app/controllers/users/passwords_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# frozen_string_literal: true

class Users::PasswordsController < Devise::PasswordsController
# POST /resource/password
def create
self.resource = resource_class.send_reset_password_instructions(resource_params)

if successfully_sent?(resource)
render json: resource, status: :ok
else
render json: resource.errors.messages, status: :unprocessable_entity
end
end

# PUT /resource/password
def update
self.resource = resource_class.reset_password_by_token(resource_params)

if resource.errors.empty?
resource.unlock_access! if unlockable?(resource)
render json: resource, status: :ok
else
render json: resource.errors.messages, status: :unprocessable_entity
end
end
end
78 changes: 4 additions & 74 deletions app/controllers/users/registrations_controller.rb
Original file line number Diff line number Diff line change
@@ -1,93 +1,23 @@
# frozen_string_literal: true

class Users::RegistrationsController < Devise::RegistrationsController
# before_action :configure_sign_up_params, only: [:create]
# before_action :configure_account_update_params, only: [:update]

# GET /resource/sign_up
# def new
# super
# end

# POST /resource
def create
build_resource(sign_up_params.merge(role: :user)) # HINT: Every higher role needs manual upgrade by an admin.
resource.save

if resource.save
if resource.persisted?
render json: resource, status: :ok
else
clean_up_passwords resource
render json: resource.errors.messages, status: :unprocessable_entity
end
end

# GET /resource/edit
# def edit
# super
# end

# PUT /resource
# def update
# super
# end

# DELETE /resource
# def destroy
# super
# end

# GET /resource/cancel
# Forces the session data which is usually expired after sign
# in to be expired now. This is useful if the user wants to
# cancel oauth signing in/up in the middle of the process,
# removing all OAuth session data.
# def cancel
# super
# end

# protected

# If you have extra params to permit, append them to the sanitizer.
# def configure_sign_up_params
# devise_parameter_sanitizer.permit(:sign_up, keys: [:attribute])
# end

# If you have extra params to permit, append them to the sanitizer.
# def configure_account_update_params
# devise_parameter_sanitizer.permit(:account_update, keys: [:attribute])
# end

# The path used after sign up.
# def after_sign_up_path_for(resource)
# super(resource)
# end

# The path used after sign up for inactive accounts.
# def after_inactive_sign_up_path_for(resource)
# super(resource)
# end

private

# def application = @application ||= Doorkeeper::Application.find_by!(uid: sign_up_params[:client_id])
#
# def access_token = @access_token ||= Doorkeeper::AccessToken.create(
# expires_in: Doorkeeper.configuration.access_token_expires_in.to_i,
# resource_owner_id: resource.id,
# refresh_token: generate_refresh_token,
# application:
# )
#
# def generate_refresh_token
# loop do
# # generate a random token string and return it,
# # unless there is already another token with the same string
# token = SecureRandom.hex(32)
# break token unless Doorkeeper::AccessToken.exists?(refresh_token: token)
# end
# end

def sign_up_params
devise_parameter_sanitizer.permit(:sign_up, keys: [:email, :password, :name])
devise_parameter_sanitizer.permit(:sign_up, keys: [:name])
devise_parameter_sanitizer.sanitize(:sign_up)
end
end
2 changes: 1 addition & 1 deletion app/grape/api/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@ class Base < Grape::API
end

mount API::V1::Trackings
add_swagger_documentation host: ENV["HOST_URI"]
add_swagger_documentation host: "#{ENV["APP_HOST"]}:#{ENV["APP_PORT"]}"
end
end
78 changes: 63 additions & 15 deletions app/javascript/application.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,20 @@ import React, {
import {
createRoot,
} from 'react-dom/client';
import {
BrowserRouter,
Route,
Routes,
} from 'react-router-dom';
import {
Login,
} from './components/Login';
import {
NewPassword,
} from './components/NewPassword';
import {
PasswordReset,
} from './components/PasswordReset';
import {
Registration,
} from './components/Registration';
Expand All @@ -24,9 +35,21 @@ import {
import {
Padding,
} from './components/custom-styling/Padding';
import {
NotFound,
} from './components/error-handling/NotFound';
import {
ConfirmationError,
} from './components/registration/ConfirmationError';
import {
ConfirmationSuccessful,
} from './components/registration/ConfirmationSuccessful';
import {
container,
} from './container';
import {
PasswordChangeContext,
} from './contexts/PasswordChangeContext';
import {
RegisterContext,
} from './contexts/RegisterContext';
Expand Down Expand Up @@ -55,6 +78,11 @@ const App: React.FC = () => {
setRegister,
] = useState(false);

const [
passwordChange,
setPasswordChange,
] = useState(null);

const userProviderValue = useMemo(() => {
return {
setUser,
Expand All @@ -74,28 +102,48 @@ const App: React.FC = () => {
register,
]);

const passwordChangeProviderValue = useMemo(() => {
return {
passwordChange,
setPasswordChange,
};
}, [
passwordChange,
]);

useEffect(() => {
storeUserInLocalStorage(user);
}, [
user,
]);

return (
<UserContext.Provider value={userProviderValue}>
<RegisterContext.Provider value={registerProviderValue}>
<Padding>
<Header>
<Row justify='space-between'>
<Col><Title>Repository-Tracker</Title></Col>
<Col><Login /></Col>
</Row>
</Header>
<Row justify='center'>
{register ? <Registration /> : <SmartTable />}
</Row>
</Padding>
</RegisterContext.Provider>
</UserContext.Provider>
<BrowserRouter>
<UserContext.Provider value={userProviderValue}>
<RegisterContext.Provider value={registerProviderValue}>
<PasswordChangeContext.Provider value={passwordChangeProviderValue}>
<Padding>
<Header>
<Row justify='space-between'>
<Col><Title>Repository-Tracker</Title></Col>
<Col><Login /></Col>
</Row>
</Header>
<Row justify='center'>
<Routes>
<Route element={register ? <Registration /> : <SmartTable />} path='/' />
<Route element={<ConfirmationSuccessful />} path='/spa/confirmation_successful' />
<Route element={<ConfirmationError />} path='/spa/confirmation_error' />
<Route element={<PasswordReset />} path='/spa/password_reset' />
<Route element={<NewPassword />} path='/spa/new_password/*' />
<Route element={<NotFound />} path='/spa/*' />
</Routes>
</Row>
</Padding>
</PasswordChangeContext.Provider>
</RegisterContext.Provider>
</UserContext.Provider>
</BrowserRouter>
);
};

Expand Down
31 changes: 0 additions & 31 deletions app/javascript/components/AutoCompleteSearch.tsx

This file was deleted.

11 changes: 0 additions & 11 deletions app/javascript/components/CustomFilterIcon.tsx

This file was deleted.

Loading