@@ -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})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user