parent
eab33bfd9a
commit
8b1de30204
@ -32,7 +32,6 @@ type ValidateTokenResponse = {
|
|||||||
const UserRequiredRoute: React.FC<any> = ({ children }) => {
|
const UserRequiredRoute: React.FC<any> = ({ children }) => {
|
||||||
const { user } = useCurrentUser();
|
const { user } = useCurrentUser();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
console.log('user required', user);
|
|
||||||
if (user) {
|
if (user) {
|
||||||
return children;
|
return children;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import Confirm from 'shared/components/Confirm';
|
import Confirm from 'shared/components/Confirm';
|
||||||
import { useHistory, useLocation } from 'react-router';
|
import { useHistory, useLocation } from 'react-router';
|
||||||
import * as QueryString from 'query-string';
|
import * as QueryString from 'query-string';
|
||||||
@ -9,35 +9,34 @@ const UsersConfirm = () => {
|
|||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const params = QueryString.parse(location.search);
|
const params = QueryString.parse(location.search);
|
||||||
|
const [hasFailed, setFailed] = useState(false);
|
||||||
const { setUser } = useCurrentUser();
|
const { setUser } = useCurrentUser();
|
||||||
|
useEffect(() => {
|
||||||
|
fetch('/auth/confirm', {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify({
|
||||||
|
confirmToken: params.confirmToken,
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
.then(async (x) => {
|
||||||
|
const { status } = x;
|
||||||
|
if (status === 200) {
|
||||||
|
const response = await x.json();
|
||||||
|
const { userID } = response;
|
||||||
|
setUser(userID);
|
||||||
|
history.push('/');
|
||||||
|
} else {
|
||||||
|
setFailed(true);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
setFailed(false);
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<LoginWrapper>
|
<LoginWrapper>
|
||||||
<Confirm
|
<Confirm hasConfirmToken={params.confirmToken !== undefined} hasFailed={hasFailed} />
|
||||||
hasConfirmToken={params.confirmToken !== undefined}
|
|
||||||
onConfirmUser={setFailed => {
|
|
||||||
fetch('/auth/confirm', {
|
|
||||||
method: 'POST',
|
|
||||||
body: JSON.stringify({
|
|
||||||
confirmToken: params.confirmToken,
|
|
||||||
}),
|
|
||||||
})
|
|
||||||
.then(async x => {
|
|
||||||
const { status } = x;
|
|
||||||
if (status === 200) {
|
|
||||||
const response = await x.json();
|
|
||||||
const { userID } = response;
|
|
||||||
setUser(userID);
|
|
||||||
history.push('/');
|
|
||||||
} else {
|
|
||||||
setFailed();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
setFailed();
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</LoginWrapper>
|
</LoginWrapper>
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
|
@ -17,6 +17,7 @@ const UsersRegister = () => {
|
|||||||
<Register
|
<Register
|
||||||
registered={registered}
|
registered={registered}
|
||||||
onSubmit={(data, setComplete, setError) => {
|
onSubmit={(data, setComplete, setError) => {
|
||||||
|
let isRedirected = false;
|
||||||
if (data.password !== data.password_confirm) {
|
if (data.password !== data.password_confirm) {
|
||||||
setError('password', { type: 'error', message: 'Passwords must match' });
|
setError('password', { type: 'error', message: 'Passwords must match' });
|
||||||
setError('password_confirm', { type: 'error', message: 'Passwords must match' });
|
setError('password_confirm', { type: 'error', message: 'Passwords must match' });
|
||||||
@ -41,17 +42,21 @@ const UsersRegister = () => {
|
|||||||
console.log(response);
|
console.log(response);
|
||||||
if (setup) {
|
if (setup) {
|
||||||
history.replace(`/confirm?confirmToken=xxxx`);
|
history.replace(`/confirm?confirmToken=xxxx`);
|
||||||
|
isRedirected = true;
|
||||||
} else if (params.confirmToken) {
|
} else if (params.confirmToken) {
|
||||||
history.replace(`/confirm?confirmToken=${params.confirmToken}`);
|
history.replace(`/confirm?confirmToken=${params.confirmToken}`);
|
||||||
|
isRedirected = true;
|
||||||
} else {
|
} else {
|
||||||
setRegistered(true);
|
setRegistered(true);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch((e) => {
|
||||||
toast('There was an issue trying to register');
|
toast('There was an issue trying to register');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
setComplete(true);
|
if (!isRedirected) {
|
||||||
|
setComplete(true);
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</LoginWrapper>
|
</LoginWrapper>
|
||||||
|
@ -21,14 +21,7 @@ import {
|
|||||||
SubTitle,
|
SubTitle,
|
||||||
} from './Styles';
|
} from './Styles';
|
||||||
|
|
||||||
const Confirm = ({ onConfirmUser, hasConfirmToken }: ConfirmProps) => {
|
const Confirm = ({ hasFailed, hasConfirmToken }: ConfirmProps) => {
|
||||||
const [hasFailed, setFailed] = useState(false);
|
|
||||||
const setHasFailed = () => {
|
|
||||||
setFailed(true);
|
|
||||||
};
|
|
||||||
useEffect(() => {
|
|
||||||
onConfirmUser(setHasFailed);
|
|
||||||
});
|
|
||||||
return (
|
return (
|
||||||
<Wrapper>
|
<Wrapper>
|
||||||
<Column>
|
<Column>
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import AccessAccount from 'shared/undraw/AccessAccount';
|
import AccessAccount from 'shared/undraw/AccessAccount';
|
||||||
import { User, Lock, Taskcafe } from 'shared/icons';
|
import { User, Lock, Taskcafe } from 'shared/icons';
|
||||||
import { useForm } from 'react-hook-form';
|
import { useForm } from 'react-hook-form';
|
||||||
|
import { useHistory } from 'react-router';
|
||||||
import LoadingSpinner from 'shared/components/LoadingSpinner';
|
import LoadingSpinner from 'shared/components/LoadingSpinner';
|
||||||
import {
|
import {
|
||||||
Form,
|
Form,
|
||||||
@ -25,6 +25,7 @@ import {
|
|||||||
|
|
||||||
const Login = ({ onSubmit }: LoginProps) => {
|
const Login = ({ onSubmit }: LoginProps) => {
|
||||||
const [isComplete, setComplete] = useState(true);
|
const [isComplete, setComplete] = useState(true);
|
||||||
|
const [showRegistration, setShowRegistration] = useState(false);
|
||||||
const {
|
const {
|
||||||
register,
|
register,
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
@ -35,6 +36,17 @@ const Login = ({ onSubmit }: LoginProps) => {
|
|||||||
setComplete(false);
|
setComplete(false);
|
||||||
onSubmit(data, setComplete, setError);
|
onSubmit(data, setComplete, setError);
|
||||||
};
|
};
|
||||||
|
const history = useHistory();
|
||||||
|
useEffect(() => {
|
||||||
|
fetch('/settings').then(async (x) => {
|
||||||
|
const { isConfigured, allowPublicRegistration } = await x.json();
|
||||||
|
if (!isConfigured) {
|
||||||
|
history.push('/register');
|
||||||
|
} else if (allowPublicRegistration) {
|
||||||
|
setShowRegistration(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
return (
|
return (
|
||||||
<Wrapper>
|
<Wrapper>
|
||||||
<Column>
|
<Column>
|
||||||
@ -68,7 +80,7 @@ const Login = ({ onSubmit }: LoginProps) => {
|
|||||||
{errors.password && <FormError>{errors.password.message}</FormError>}
|
{errors.password && <FormError>{errors.password.message}</FormError>}
|
||||||
|
|
||||||
<ActionButtons>
|
<ActionButtons>
|
||||||
<RegisterButton variant="outline">Register</RegisterButton>
|
{showRegistration ? <RegisterButton variant="outline">Register</RegisterButton> : <div />}
|
||||||
{!isComplete && <LoadingSpinner size="32px" thickness="2px" borderSize="48px" />}
|
{!isComplete && <LoadingSpinner size="32px" thickness="2px" borderSize="48px" />}
|
||||||
<LoginButton type="submit" disabled={!isComplete}>
|
<LoginButton type="submit" disabled={!isComplete}>
|
||||||
Login
|
Login
|
||||||
|
2
frontend/src/taskcafe.d.ts
vendored
2
frontend/src/taskcafe.d.ts
vendored
@ -89,7 +89,7 @@ type ErrorOption =
|
|||||||
type SetFailedFn = () => void;
|
type SetFailedFn = () => void;
|
||||||
type ConfirmProps = {
|
type ConfirmProps = {
|
||||||
hasConfirmToken: boolean;
|
hasConfirmToken: boolean;
|
||||||
onConfirmUser: (setFailed: SetFailedFn) => void;
|
hasFailed: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
type RegisterProps = {
|
type RegisterProps = {
|
||||||
|
@ -102,6 +102,7 @@ func NewRouter(dbConnection *sqlx.DB, emailConfig utils.EmailConfig, securityCon
|
|||||||
mux.Mount("/uploads/", http.StripPrefix("/uploads/", imgServer))
|
mux.Mount("/uploads/", http.StripPrefix("/uploads/", imgServer))
|
||||||
mux.Post("/auth/confirm", taskcafeHandler.ConfirmUser)
|
mux.Post("/auth/confirm", taskcafeHandler.ConfirmUser)
|
||||||
mux.Post("/auth/register", taskcafeHandler.RegisterUser)
|
mux.Post("/auth/register", taskcafeHandler.RegisterUser)
|
||||||
|
mux.Get("/settings", taskcafeHandler.PublicSettings)
|
||||||
})
|
})
|
||||||
auth := AuthenticationMiddleware{*repository}
|
auth := AuthenticationMiddleware{*repository}
|
||||||
r.Group(func(mux chi.Router) {
|
r.Group(func(mux chi.Router) {
|
||||||
|
23
internal/route/settings.go
Normal file
23
internal/route/settings.go
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package route
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PublicSettingsResponse struct {
|
||||||
|
IsConfigured bool `json:"isConfigured"`
|
||||||
|
AllowPublicRegistration bool `json:"allowPublicRegistration"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *TaskcafeHandler) PublicSettings(w http.ResponseWriter, r *http.Request) {
|
||||||
|
userExists, err := h.repo.HasAnyUser(r.Context())
|
||||||
|
if err != nil {
|
||||||
|
log.WithError(err).Error("issue checking if user accounts exist")
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
json.NewEncoder(w).Encode(PublicSettingsResponse{IsConfigured: userExists, AllowPublicRegistration: false})
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user