[DEPRECATE] Remove Google Analytics (#1021)
* it doesn't work with our current CSP * it's probably not used by anyone * it isn't in harmony with our security purposes * literally removes all use of it * suggestions from code review * remove useless test. Co-authored-by: Amir Zarrinkafsh <nightah@me.com> Co-authored-by: Clement Michaud <clement.michaud34@gmail.com>pull/1023/head
parent
991ce29e4b
commit
a4cf2e675f
|
@ -39,11 +39,6 @@ jwt_secret: a_very_important_secret
|
||||||
# be redirected upon successful authentication.
|
# be redirected upon successful authentication.
|
||||||
default_redirection_url: https://home.example.com:8080/
|
default_redirection_url: https://home.example.com:8080/
|
||||||
|
|
||||||
# Google Analytics Tracking ID to track the usage of the portal
|
|
||||||
# using a Google Analytics dashboard.
|
|
||||||
#
|
|
||||||
## google_analytics: UA-00000-01
|
|
||||||
|
|
||||||
# TOTP Settings
|
# TOTP Settings
|
||||||
#
|
#
|
||||||
# Parameters used for TOTP generation
|
# Parameters used for TOTP generation
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
layout: default
|
layout: default
|
||||||
title: Access Control
|
title: Access Control
|
||||||
parent: Configuration
|
parent: Configuration
|
||||||
nav_order: 2
|
nav_order: 1
|
||||||
---
|
---
|
||||||
|
|
||||||
# Access Control
|
# Access Control
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
layout: default
|
layout: default
|
||||||
title: Duo Push Notifications
|
title: Duo Push Notifications
|
||||||
parent: Configuration
|
parent: Configuration
|
||||||
nav_order: 3
|
nav_order: 2
|
||||||
---
|
---
|
||||||
|
|
||||||
# Duo Push Notifications
|
# Duo Push Notifications
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
---
|
|
||||||
layout: default
|
|
||||||
title: Google Analytics
|
|
||||||
parent: Configuration
|
|
||||||
nav_order: 4
|
|
||||||
---
|
|
||||||
|
|
||||||
# Google Analytics
|
|
||||||
|
|
||||||
It is possible to provide a Google Analytics ID to Authelia in order
|
|
||||||
to monitor the usage of the Sign-In portal.
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
google_analytics: UA-00000-01
|
|
||||||
```
|
|
|
@ -2,7 +2,7 @@
|
||||||
layout: default
|
layout: default
|
||||||
title: Miscellaneous
|
title: Miscellaneous
|
||||||
parent: Configuration
|
parent: Configuration
|
||||||
nav_order: 5
|
nav_order: 3
|
||||||
---
|
---
|
||||||
|
|
||||||
# Miscellaneous
|
# Miscellaneous
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
layout: default
|
layout: default
|
||||||
title: One-Time Password
|
title: One-Time Password
|
||||||
parent: Configuration
|
parent: Configuration
|
||||||
nav_order: 6
|
nav_order: 4
|
||||||
---
|
---
|
||||||
|
|
||||||
# One-Time Password
|
# One-Time Password
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
layout: default
|
layout: default
|
||||||
title: Regulation
|
title: Regulation
|
||||||
parent: Configuration
|
parent: Configuration
|
||||||
nav_order: 7
|
nav_order: 5
|
||||||
---
|
---
|
||||||
|
|
||||||
# Regulation
|
# Regulation
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
layout: default
|
layout: default
|
||||||
title: Secrets
|
title: Secrets
|
||||||
parent: Configuration
|
parent: Configuration
|
||||||
nav_order: 8
|
nav_order: 6
|
||||||
---
|
---
|
||||||
|
|
||||||
# Secrets
|
# Secrets
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
layout: default
|
layout: default
|
||||||
title: Server
|
title: Server
|
||||||
parent: Configuration
|
parent: Configuration
|
||||||
nav_order: 9
|
nav_order: 7
|
||||||
---
|
---
|
||||||
|
|
||||||
# Server
|
# Server
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
layout: default
|
layout: default
|
||||||
title: Session
|
title: Session
|
||||||
parent: Configuration
|
parent: Configuration
|
||||||
nav_order: 10
|
nav_order: 8
|
||||||
---
|
---
|
||||||
|
|
||||||
# Session
|
# Session
|
||||||
|
|
|
@ -2,17 +2,15 @@ package schema
|
||||||
|
|
||||||
// Configuration object extracted from YAML configuration file.
|
// Configuration object extracted from YAML configuration file.
|
||||||
type Configuration struct {
|
type Configuration struct {
|
||||||
Host string `mapstructure:"host"`
|
Host string `mapstructure:"host"`
|
||||||
Port int `mapstructure:"port"`
|
Port int `mapstructure:"port"`
|
||||||
TLSCert string `mapstructure:"tls_cert"`
|
TLSCert string `mapstructure:"tls_cert"`
|
||||||
TLSKey string `mapstructure:"tls_key"`
|
TLSKey string `mapstructure:"tls_key"`
|
||||||
LogLevel string `mapstructure:"log_level"`
|
LogLevel string `mapstructure:"log_level"`
|
||||||
LogFilePath string `mapstructure:"log_file_path"`
|
LogFilePath string `mapstructure:"log_file_path"`
|
||||||
JWTSecret string `mapstructure:"jwt_secret"`
|
JWTSecret string `mapstructure:"jwt_secret"`
|
||||||
DefaultRedirectionURL string `mapstructure:"default_redirection_url"`
|
DefaultRedirectionURL string `mapstructure:"default_redirection_url"`
|
||||||
GoogleAnalyticsTrackingID string `mapstructure:"google_analytics"`
|
|
||||||
|
|
||||||
// TODO: Consider refactoring the following pointers as they don't seem to need to be pointers: TOTP, Notifier, Regulation
|
|
||||||
AuthenticationBackend AuthenticationBackendConfiguration `mapstructure:"authentication_backend"`
|
AuthenticationBackend AuthenticationBackendConfiguration `mapstructure:"authentication_backend"`
|
||||||
Session SessionConfiguration `mapstructure:"session"`
|
Session SessionConfiguration `mapstructure:"session"`
|
||||||
TOTP *TOTPConfiguration `mapstructure:"totp"`
|
TOTP *TOTPConfiguration `mapstructure:"totp"`
|
||||||
|
|
|
@ -10,18 +10,17 @@ var validKeys = []string{
|
||||||
"jwt_secret",
|
"jwt_secret",
|
||||||
"tls_key",
|
"tls_key",
|
||||||
"tls_cert",
|
"tls_cert",
|
||||||
"google_analytics",
|
|
||||||
|
|
||||||
// Server Keys.
|
// Server Keys.
|
||||||
"server.read_buffer_size",
|
"server.read_buffer_size",
|
||||||
"server.write_buffer_size",
|
"server.write_buffer_size",
|
||||||
|
|
||||||
// TOTP Keys
|
// TOTP Keys.
|
||||||
"totp.issuer",
|
"totp.issuer",
|
||||||
"totp.period",
|
"totp.period",
|
||||||
"totp.skew",
|
"totp.skew",
|
||||||
|
|
||||||
// Access Control Keys
|
// Access Control Keys.
|
||||||
"access_control.rules",
|
"access_control.rules",
|
||||||
"access_control.default_policy",
|
"access_control.default_policy",
|
||||||
|
|
||||||
|
@ -130,8 +129,9 @@ var validKeys = []string{
|
||||||
}
|
}
|
||||||
|
|
||||||
var specificErrorKeys = map[string]string{
|
var specificErrorKeys = map[string]string{
|
||||||
"logs_file_path": "config key replaced: logs_file is now log_file",
|
"logs_file_path": "config key replaced: logs_file is now log_file",
|
||||||
"logs_level": "config key replaced: logs_level is now log_level",
|
"logs_level": "config key replaced: logs_level is now log_level",
|
||||||
|
"google_analytics": "config key removed: google_analytics - this functionality has been deprecated",
|
||||||
"authentication_backend.file.password_options.algorithm": "config key incorrect: authentication_backend.file.password_options should be authentication_backend.file.password",
|
"authentication_backend.file.password_options.algorithm": "config key incorrect: authentication_backend.file.password_options should be authentication_backend.file.password",
|
||||||
"authentication_backend.file.password_options.iterations": "config key incorrect: authentication_backend.file.password_options should be authentication_backend.file.password",
|
"authentication_backend.file.password_options.iterations": "config key incorrect: authentication_backend.file.password_options should be authentication_backend.file.password",
|
||||||
"authentication_backend.file.password_options.key_length": "config key incorrect: authentication_backend.file.password_options should be authentication_backend.file.password",
|
"authentication_backend.file.password_options.key_length": "config key incorrect: authentication_backend.file.password_options should be authentication_backend.file.password",
|
||||||
|
|
|
@ -35,7 +35,6 @@ const unableToRegisterSecurityKeyMessage = "Unable to register your security key
|
||||||
const unableToResetPasswordMessage = "Unable to reset your password."
|
const unableToResetPasswordMessage = "Unable to reset your password."
|
||||||
const mfaValidationFailedMessage = "Authentication failed, please retry later."
|
const mfaValidationFailedMessage = "Authentication failed, please retry later."
|
||||||
|
|
||||||
const testGATrackingID = "ABC"
|
|
||||||
const testInactivity = "10"
|
const testInactivity = "10"
|
||||||
const testRedirectionURL = "http://redirection.local"
|
const testRedirectionURL = "http://redirection.local"
|
||||||
const testResultAllow = "allow"
|
const testResultAllow = "allow"
|
||||||
|
|
|
@ -4,17 +4,15 @@ import "github.com/authelia/authelia/internal/middlewares"
|
||||||
|
|
||||||
// ConfigurationBody configuration parameters exposed to the frontend.
|
// ConfigurationBody configuration parameters exposed to the frontend.
|
||||||
type ConfigurationBody struct {
|
type ConfigurationBody struct {
|
||||||
GoogleAnalyticsTrackingID string `json:"ga_tracking_id,omitempty"`
|
RememberMe bool `json:"remember_me"` // whether remember me is enabled or not
|
||||||
RememberMe bool `json:"remember_me"` // whether remember me is enabled or not
|
ResetPassword bool `json:"reset_password"`
|
||||||
ResetPassword bool `json:"reset_password"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConfigurationGet fetches configuration parameters for frontend mutation.
|
// ConfigurationGet fetches configuration parameters for frontend mutation.
|
||||||
func ConfigurationGet(ctx *middlewares.AutheliaCtx) {
|
func ConfigurationGet(ctx *middlewares.AutheliaCtx) {
|
||||||
body := ConfigurationBody{
|
body := ConfigurationBody{
|
||||||
GoogleAnalyticsTrackingID: ctx.Configuration.GoogleAnalyticsTrackingID,
|
RememberMe: ctx.Providers.SessionProvider.RememberMe != 0,
|
||||||
RememberMe: ctx.Providers.SessionProvider.RememberMe != 0,
|
ResetPassword: !ctx.Configuration.AuthenticationBackend.DisableResetPassword,
|
||||||
ResetPassword: !ctx.Configuration.AuthenticationBackend.DisableResetPassword,
|
|
||||||
}
|
}
|
||||||
ctx.SetJSONBody(body) //nolint:errcheck // TODO: Legacy code, consider refactoring time permitting.
|
ctx.SetJSONBody(body) //nolint:errcheck // TODO: Legacy code, consider refactoring time permitting.
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ import (
|
||||||
|
|
||||||
"github.com/stretchr/testify/suite"
|
"github.com/stretchr/testify/suite"
|
||||||
|
|
||||||
"github.com/authelia/authelia/internal/configuration/schema"
|
|
||||||
"github.com/authelia/authelia/internal/mocks"
|
"github.com/authelia/authelia/internal/mocks"
|
||||||
"github.com/authelia/authelia/internal/session"
|
"github.com/authelia/authelia/internal/session"
|
||||||
)
|
)
|
||||||
|
@ -24,31 +23,13 @@ func (s *ConfigurationSuite) TearDownTest() {
|
||||||
s.mock.Close()
|
s.mock.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ConfigurationSuite) TestShouldReturnConfiguredGATrackingID() {
|
|
||||||
GATrackingID := testGATrackingID
|
|
||||||
s.mock.Ctx.Configuration.GoogleAnalyticsTrackingID = GATrackingID
|
|
||||||
s.mock.Ctx.Configuration.Session.RememberMeDuration = schema.DefaultSessionConfiguration.RememberMeDuration
|
|
||||||
|
|
||||||
expectedBody := ConfigurationBody{
|
|
||||||
GoogleAnalyticsTrackingID: GATrackingID,
|
|
||||||
RememberMe: true,
|
|
||||||
ResetPassword: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
ConfigurationGet(s.mock.Ctx)
|
|
||||||
s.mock.Assert200OK(s.T(), expectedBody)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ConfigurationSuite) TestShouldDisableRememberMe() {
|
func (s *ConfigurationSuite) TestShouldDisableRememberMe() {
|
||||||
GATrackingID := testGATrackingID
|
|
||||||
s.mock.Ctx.Configuration.GoogleAnalyticsTrackingID = GATrackingID
|
|
||||||
s.mock.Ctx.Configuration.Session.RememberMeDuration = "0"
|
s.mock.Ctx.Configuration.Session.RememberMeDuration = "0"
|
||||||
s.mock.Ctx.Providers.SessionProvider = session.NewProvider(
|
s.mock.Ctx.Providers.SessionProvider = session.NewProvider(
|
||||||
s.mock.Ctx.Configuration.Session)
|
s.mock.Ctx.Configuration.Session)
|
||||||
expectedBody := ConfigurationBody{
|
expectedBody := ConfigurationBody{
|
||||||
GoogleAnalyticsTrackingID: GATrackingID,
|
RememberMe: false,
|
||||||
RememberMe: false,
|
ResetPassword: true,
|
||||||
ResetPassword: true,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigurationGet(s.mock.Ctx)
|
ConfigurationGet(s.mock.Ctx)
|
||||||
|
@ -56,13 +37,10 @@ func (s *ConfigurationSuite) TestShouldDisableRememberMe() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ConfigurationSuite) TestShouldDisableResetPassword() {
|
func (s *ConfigurationSuite) TestShouldDisableResetPassword() {
|
||||||
GATrackingID := testGATrackingID
|
|
||||||
s.mock.Ctx.Configuration.GoogleAnalyticsTrackingID = GATrackingID
|
|
||||||
s.mock.Ctx.Configuration.AuthenticationBackend.DisableResetPassword = true
|
s.mock.Ctx.Configuration.AuthenticationBackend.DisableResetPassword = true
|
||||||
expectedBody := ConfigurationBody{
|
expectedBody := ConfigurationBody{
|
||||||
GoogleAnalyticsTrackingID: GATrackingID,
|
RememberMe: true,
|
||||||
RememberMe: true,
|
ResetPassword: false,
|
||||||
ResetPassword: false,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigurationGet(s.mock.Ctx)
|
ConfigurationGet(s.mock.Ctx)
|
||||||
|
|
|
@ -18,8 +18,6 @@ import { Notification } from './models/Notifications';
|
||||||
import NotificationBar from './components/NotificationBar';
|
import NotificationBar from './components/NotificationBar';
|
||||||
import SignOut from './views/LoginPortal/SignOut/SignOut';
|
import SignOut from './views/LoginPortal/SignOut/SignOut';
|
||||||
import { useConfiguration } from './hooks/Configuration';
|
import { useConfiguration } from './hooks/Configuration';
|
||||||
import Tracker from "./components/Tracker";
|
|
||||||
import { useTracking } from "./hooks/Tracking";
|
|
||||||
import '@fortawesome/fontawesome-svg-core/styles.css'
|
import '@fortawesome/fontawesome-svg-core/styles.css'
|
||||||
import {config as faConfig} from '@fortawesome/fontawesome-svg-core';
|
import {config as faConfig} from '@fortawesome/fontawesome-svg-core';
|
||||||
|
|
||||||
|
@ -28,7 +26,6 @@ faConfig.autoAddCss = false;
|
||||||
const App: React.FC = () => {
|
const App: React.FC = () => {
|
||||||
const [notification, setNotification] = useState(null as Notification | null);
|
const [notification, setNotification] = useState(null as Notification | null);
|
||||||
const [configuration, fetchConfig, , fetchConfigError] = useConfiguration();
|
const [configuration, fetchConfig, , fetchConfigError] = useConfiguration();
|
||||||
const tracker = useTracking(configuration);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (fetchConfigError) {
|
if (fetchConfigError) {
|
||||||
|
@ -41,34 +38,32 @@ const App: React.FC = () => {
|
||||||
return (
|
return (
|
||||||
<NotificationsContext.Provider value={{ notification, setNotification }} >
|
<NotificationsContext.Provider value={{ notification, setNotification }} >
|
||||||
<Router>
|
<Router>
|
||||||
<Tracker tracker={tracker}>
|
<NotificationBar onClose={() => setNotification(null)} />
|
||||||
<NotificationBar onClose={() => setNotification(null)} />
|
<Switch>
|
||||||
<Switch>
|
<Route path={ResetPasswordStep1Route} exact>
|
||||||
<Route path={ResetPasswordStep1Route} exact>
|
<ResetPasswordStep1 />
|
||||||
<ResetPasswordStep1 />
|
</Route>
|
||||||
</Route>
|
<Route path={ResetPasswordStep2Route} exact>
|
||||||
<Route path={ResetPasswordStep2Route} exact>
|
<ResetPasswordStep2 />
|
||||||
<ResetPasswordStep2 />
|
</Route>
|
||||||
</Route>
|
<Route path={RegisterSecurityKeyRoute} exact>
|
||||||
<Route path={RegisterSecurityKeyRoute} exact>
|
<RegisterSecurityKey />
|
||||||
<RegisterSecurityKey />
|
</Route>
|
||||||
</Route>
|
<Route path={RegisterOneTimePasswordRoute} exact>
|
||||||
<Route path={RegisterOneTimePasswordRoute} exact>
|
<RegisterOneTimePassword />
|
||||||
<RegisterOneTimePassword />
|
</Route>
|
||||||
</Route>
|
<Route path={LogoutRoute} exact>
|
||||||
<Route path={LogoutRoute} exact>
|
<SignOut />
|
||||||
<SignOut />
|
</Route>
|
||||||
</Route>
|
<Route path={FirstFactorRoute}>
|
||||||
<Route path={FirstFactorRoute}>
|
<LoginPortal
|
||||||
<LoginPortal
|
rememberMe={configuration?.remember_me === true}
|
||||||
rememberMe={configuration?.remember_me === true}
|
resetPassword={configuration?.reset_password === true} />
|
||||||
resetPassword={configuration?.reset_password === true} />
|
</Route>
|
||||||
</Route>
|
<Route path="/">
|
||||||
<Route path="/">
|
<Redirect to={FirstFactorRoute}></Redirect>
|
||||||
<Redirect to={FirstFactorRoute}></Redirect>
|
</Route>
|
||||||
</Route>
|
</Switch>
|
||||||
</Switch>
|
|
||||||
</Tracker>
|
|
||||||
</Router>
|
</Router>
|
||||||
</NotificationsContext.Provider>
|
</NotificationsContext.Provider>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { mount } from "enzyme";
|
|
||||||
import Tracker from "./Tracker";
|
|
||||||
|
|
||||||
import { MemoryRouter as Router } from 'react-router-dom';
|
|
||||||
|
|
||||||
const mountWithRouter = node => mount(<Router>{node}</Router>);
|
|
||||||
|
|
||||||
it('renders without crashing', () => {
|
|
||||||
mountWithRouter(<Tracker trackingIDs={[]} />);
|
|
||||||
});
|
|
|
@ -1,35 +0,0 @@
|
||||||
import React, { useEffect, useCallback, Fragment, ReactNode } from "react";
|
|
||||||
import { useLocation } from "react-router";
|
|
||||||
import ReactGA, { Tracker } from "react-ga";
|
|
||||||
|
|
||||||
export interface Props {
|
|
||||||
tracker: Tracker | undefined;
|
|
||||||
children?: ReactNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function (props: Props) {
|
|
||||||
const location = useLocation();
|
|
||||||
|
|
||||||
const trackPage = useCallback((page: string) => {
|
|
||||||
if (props.tracker) {
|
|
||||||
ReactGA.set({ page });
|
|
||||||
ReactGA.pageview(page);
|
|
||||||
}
|
|
||||||
}, [props.tracker]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (props.tracker) {
|
|
||||||
ReactGA.initialize([props.tracker]);
|
|
||||||
}
|
|
||||||
}, [props.tracker]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
trackPage(location.pathname + location.search);
|
|
||||||
}, [trackPage, location.pathname, location.search]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Fragment>
|
|
||||||
{props.children}
|
|
||||||
</Fragment>
|
|
||||||
)
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
import { useState, useEffect } from "react";
|
|
||||||
import { Configuration } from "../models/Configuration";
|
|
||||||
import { Tracker } from "react-ga";
|
|
||||||
|
|
||||||
export function useTracking(configuration: Configuration | undefined) {
|
|
||||||
const [trackingIds, setTrackingIds] = useState(undefined as Tracker | undefined);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (configuration && configuration.ga_tracking_id) {
|
|
||||||
setTrackingIds({ trackingId: configuration.ga_tracking_id });
|
|
||||||
}
|
|
||||||
}, [configuration]);
|
|
||||||
|
|
||||||
return trackingIds;
|
|
||||||
}
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { SecondFactorMethod } from "./Methods";
|
import { SecondFactorMethod } from "./Methods";
|
||||||
|
|
||||||
export interface Configuration {
|
export interface Configuration {
|
||||||
ga_tracking_id: string;
|
|
||||||
remember_me: boolean;
|
remember_me: boolean;
|
||||||
reset_password: boolean;
|
reset_password: boolean;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue