-
,
diff --git a/client/src/pages/servapps/servapps.jsx b/client/src/pages/servapps/servapps.jsx
index d895c9b..20468bc 100644
--- a/client/src/pages/servapps/servapps.jsx
+++ b/client/src/pages/servapps/servapps.jsx
@@ -150,7 +150,7 @@ const ServeApps = () => {
} onClick={() => {
refreshServeApps();
}}>Refresh
-
+
}
@@ -303,7 +303,7 @@ const ServeApps = () => {
-
+
diff --git a/client/src/routes/LoginRoutes.jsx b/client/src/routes/LoginRoutes.jsx
index e405991..8c67afb 100644
--- a/client/src/routes/LoginRoutes.jsx
+++ b/client/src/routes/LoginRoutes.jsx
@@ -22,35 +22,35 @@ const LoginRoutes = {
element:
,
children: [
{
- path: '/ui/login',
+ path: '/cosmos-ui/login',
element:
},
{
- path: '/ui/register',
+ path: '/cosmos-ui/register',
element:
},
{
- path: '/ui/logout',
+ path: '/cosmos-ui/logout',
element:
},
{
- path: '/ui/newInstall',
+ path: '/cosmos-ui/newInstall',
element:
},
{
- path: '/ui/newmfa',
+ path: '/cosmos-ui/newmfa',
element:
},
{
- path: '/ui/openid',
+ path: '/cosmos-ui/openid',
element:
},
{
- path: '/ui/loginmfa',
+ path: '/cosmos-ui/loginmfa',
element:
},
{
- path: '/ui/forgot-password',
+ path: '/cosmos-ui/forgot-password',
element:
},
]
diff --git a/client/src/routes/MainRoutes.jsx b/client/src/routes/MainRoutes.jsx
index 4595f31..1ea2bd5 100644
--- a/client/src/routes/MainRoutes.jsx
+++ b/client/src/routes/MainRoutes.jsx
@@ -39,60 +39,60 @@ const MainRoutes = {
children: [
{
path: '/',
- // redirect to /ui
- element:
+ // redirect to /cosmos-ui
+ element:
},
{
- path: '/ui/logo',
- // redirect to /ui
+ path: '/cosmos-ui/logo',
+ // redirect to /cosmos-ui
element:
},
{
- path: '/ui',
+ path: '/cosmos-ui',
element:
},
{
- path: '/ui/dashboard',
+ path: '/cosmos-ui/dashboard',
element:
},
{
- path: '/ui/servapps',
+ path: '/cosmos-ui/servapps',
element:
},
{
- path: '/ui/config-users',
+ path: '/cosmos-ui/config-users',
element:
},
{
- path: '/ui/config-general',
+ path: '/cosmos-ui/config-general',
element:
},
{
- path: '/ui/servapps/new-service',
+ path: '/cosmos-ui/servapps/new-service',
element:
},
{
- path: '/ui/config-url',
+ path: '/cosmos-ui/config-url',
element:
},
{
- path: '/ui/config-url/:routeName',
+ path: '/cosmos-ui/config-url/:routeName',
element:
,
},
{
- path: '/ui/servapps/containers/:containerName',
+ path: '/cosmos-ui/servapps/containers/:containerName',
element:
,
},
{
- path: '/ui/openid-manage',
+ path: '/cosmos-ui/openid-manage',
element:
,
},
{
- path: '/ui/market-listing/',
+ path: '/cosmos-ui/market-listing/',
element:
},
{
- path: '/ui/market-listing/:appName',
+ path: '/cosmos-ui/market-listing/:appName',
element:
}
]
diff --git a/client/src/utils/indexs.js b/client/src/utils/indexs.js
index 3b20fcb..391c927 100644
--- a/client/src/utils/indexs.js
+++ b/client/src/utils/indexs.js
@@ -25,4 +25,25 @@ export function isDomain(hostname) {
}
return true;
-}
\ No newline at end of file
+}
+
+export function debounce(func, wait, immediate) {
+ var timeout;
+
+ return () => {
+ var context = this, args = arguments;
+
+ var later = () => {
+ timeout = null;
+ if (!immediate) func.apply(context, args);
+ };
+
+ var callNow = immediate && !timeout;
+
+ clearTimeout(timeout);
+
+ timeout = setTimeout(later, wait);
+
+ if (callNow) func.apply(context, args);
+ };
+};
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 9400958..68c242b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "cosmos-server",
- "version": "0.7.0-unstable",
+ "version": "0.7.0-unstable2",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "cosmos-server",
- "version": "0.7.0-unstable",
+ "version": "0.7.0-unstable2",
"dependencies": {
"@ant-design/colors": "^6.0.0",
"@ant-design/icons": "^4.7.0",
@@ -24,6 +24,7 @@
"apexcharts": "^3.35.5",
"bcryptjs": "^2.4.3",
"browserslist": "^4.21.7",
+ "dot": "^1.1.3",
"formik": "^2.2.9",
"framer-motion": "^7.3.6",
"history": "^5.3.0",
@@ -52,6 +53,8 @@
"typescript": "4.8.3",
"vite": "^4.2.0",
"web-vitals": "^3.0.2",
+ "whiskers": "^0.4.0",
+ "whiskers.js": "^1.0.0",
"yup": "^0.32.11"
},
"devDependencies": {
@@ -4391,6 +4394,11 @@
"integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==",
"dev": true
},
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
+ },
"node_modules/available-typed-arrays": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
@@ -4411,6 +4419,15 @@
"node": ">=4"
}
},
+ "node_modules/axios": {
+ "version": "0.27.2",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz",
+ "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==",
+ "dependencies": {
+ "follow-redirects": "^1.14.9",
+ "form-data": "^4.0.0"
+ }
+ },
"node_modules/axobject-query": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz",
@@ -4749,6 +4766,17 @@
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
},
+ "node_modules/combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
"node_modules/comma-separated-tokens": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz",
@@ -4997,6 +5025,14 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
"node_modules/diff-sequences": {
"version": "29.4.3",
"resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz",
@@ -5048,6 +5084,17 @@
"csstype": "^3.0.2"
}
},
+ "node_modules/dot": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/dot/-/dot-1.1.3.tgz",
+ "integrity": "sha512-/nt74Rm+PcfnirXGEdhZleTwGC2LMnuKTeeTIlI82xb5loBBoXNYzr2ezCroPSMtilK8EZIfcNZwOcHN+ib1Lg==",
+ "engines": [
+ "node >=0.2.6"
+ ],
+ "bin": {
+ "dottojs": "bin/dot-packer"
+ }
+ },
"node_modules/electron-to-chromium": {
"version": "1.4.419",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.419.tgz",
@@ -6107,6 +6154,25 @@
"integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==",
"dev": true
},
+ "node_modules/follow-redirects": {
+ "version": "1.15.2",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
+ "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/RubenVerborgh"
+ }
+ ],
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependenciesMeta": {
+ "debug": {
+ "optional": true
+ }
+ }
+ },
"node_modules/for-each": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
@@ -6115,6 +6181,19 @@
"is-callable": "^1.1.3"
}
},
+ "node_modules/form-data": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
+ "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/format": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz",
@@ -7687,6 +7766,25 @@
"node": ">=8.6"
}
},
+ "node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
"node_modules/mimic-fn": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",
@@ -9923,6 +10021,22 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/whiskers": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/whiskers/-/whiskers-0.4.0.tgz",
+ "integrity": "sha512-pTygA/fE6RIMOp3AwUy7E9jrdpqUEa4k5VCdJIBZ/64kNtiMuCTCYC6fzbiUhjxN32zX+qZQlZACMC/un5HS7A==",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/whiskers.js": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/whiskers.js/-/whiskers.js-1.0.0.tgz",
+ "integrity": "sha512-IzdNdA2jTPrTEnjQkySSOW90rtb++vJUjkHdwwsjqIeGndnizM3Mo+5DEVZ3iy7Su3itR92i9+EFtYamIT3Zxw==",
+ "dependencies": {
+ "axios": "^0.27.2"
+ }
+ },
"node_modules/word-wrap": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
diff --git a/package.json b/package.json
index a632fbb..e61bcbc 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "cosmos-server",
- "version": "0.7.0-unstable2",
+ "version": "0.7.0-unstable3",
"description": "",
"main": "test-server.js",
"bugs": {
@@ -24,6 +24,7 @@
"apexcharts": "^3.35.5",
"bcryptjs": "^2.4.3",
"browserslist": "^4.21.7",
+ "dot": "^1.1.3",
"formik": "^2.2.9",
"framer-motion": "^7.3.6",
"history": "^5.3.0",
@@ -52,11 +53,13 @@
"typescript": "4.8.3",
"vite": "^4.2.0",
"web-vitals": "^3.0.2",
+ "whiskers": "^0.4.0",
+ "whiskers.js": "^1.0.0",
"yup": "^0.32.11"
},
"scripts": {
"client": "vite",
- "client-build": "vite build --base=/ui/",
+ "client-build": "vite build --base=/cosmos-ui/",
"start": "env CONFIG_FILE=./config_dev.json EZ=UTC build/cosmos",
"build": "sh build.sh",
"dev": "npm run build && npm run start",
@@ -64,7 +67,7 @@
"dockerdevrun": "docker stop cosmos-dev; docker rm cosmos-dev; docker run -d -p 80:80 -p 443:443 -e DOCKER_HOST=tcp://host.docker.internal:2375 -e COSMOS_MONGODB=$MONGODB -e COSMOS_LOG_LEVEL=DEBUG -v /:/mnt/host --restart=unless-stopped -h cosmos-dev --name cosmos-dev cosmos-dev",
"dockerdev": "npm run dockerdevbuild && npm run dockerdevrun",
"dockerdevclient": "npm run client-build && npm run dockerdevbuild && npm run dockerdevrun",
- "demo": "vite build --base=/ui/ --mode demo",
+ "demo": "vite build --base=/cosmos-ui/ --mode demo",
"devdemo": "vite --mode demo"
},
"eslintConfig": {
diff --git a/readme.md b/readme.md
index 78aaf88..54f322f 100644
--- a/readme.md
+++ b/readme.md
@@ -5,7 +5,6 @@
Thanks to the sponsors:
-
---
@@ -24,7 +23,7 @@ Cosmos is a self-hosted platform for running server applications securely and wi
-
+
diff --git a/src/authorizationserver/oauth2_discover.go b/src/authorizationserver/oauth2_discover.go
index cd267bf..2a0addd 100644
--- a/src/authorizationserver/oauth2_discover.go
+++ b/src/authorizationserver/oauth2_discover.go
@@ -72,7 +72,7 @@ func discoverEndpoint(rw http.ResponseWriter, req *http.Request) {
json.NewEncoder(rw).Encode(&oidcConfiguration{
Issuer: hostname,
- AuthURL: realHostname + "/ui/openid",
+ AuthURL: realHostname + "/cosmos-ui/openid",
TokenURL: hostname + "/oauth2/token",
JWKsURI: hostname + "/.well-known/jwks.json",
RevocationEndpoint: hostname + "/oauth2/revoke",
@@ -96,7 +96,7 @@ func discoverEndpoint(rw http.ResponseWriter, req *http.Request) {
BackChannelLogoutSessionSupported: true,
FrontChannelLogoutSupported: true,
FrontChannelLogoutSessionSupported: true,
- EndSessionEndpoint: hostname + "/ui/logout",
+ EndSessionEndpoint: hostname + "/cosmos-ui/logout",
RequestObjectSigningAlgValuesSupported: []string{"RS256"},
CodeChallengeMethodsSupported: []string{"plain", "S256"},
})
diff --git a/src/docker/api_blueprint.go b/src/docker/api_blueprint.go
index d4f87a2..8667e58 100644
--- a/src/docker/api_blueprint.go
+++ b/src/docker/api_blueprint.go
@@ -384,7 +384,7 @@ func CreateService(serviceRequest DockerServiceCreateRequest, OnLog func(string)
if containerConfig.Env != nil {
for i, env := range containerConfig.Env {
if strings.HasPrefix(env, "TZ=") {
- if strings.TrimPrefix(env, "TZ=") == "" {
+ if strings.TrimPrefix(env, "TZ=") == "auto" {
if os.Getenv("TZ") != "" {
containerConfig.Env[i] = "TZ=" + os.Getenv("TZ")
} else {
diff --git a/src/httpServer.go b/src/httpServer.go
index 7e8f724..d012f4d 100644
--- a/src/httpServer.go
+++ b/src/httpServer.go
@@ -302,12 +302,12 @@ func StartServer() {
fs = utils.EnsureHostname(fs)
}
- router.PathPrefix("/ui").Handler(http.StripPrefix("/ui", fs))
+ router.PathPrefix("/cosmos-ui").Handler(http.StripPrefix("/cosmos-ui", fs))
router = proxy.BuildFromConfig(router, HTTPConfig.ProxyConfig)
router.HandleFunc("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- http.Redirect(w, r, "/ui", http.StatusMovedPermanently)
+ http.Redirect(w, r, "/cosmos-ui", http.StatusMovedPermanently)
}))
diff --git a/src/user/token.go b/src/user/token.go
index d54e64f..dd467bb 100644
--- a/src/user/token.go
+++ b/src/user/token.go
@@ -152,7 +152,7 @@ func RefreshUserToken(w http.ResponseWriter, req *http.Request) (utils.User, err
}
requestURL := req.URL.Path
- isSettingMFA := strings.HasPrefix(requestURL, "/ui/loginmfa") || strings.HasPrefix(requestURL, "/ui/newmfa") || strings.HasPrefix(requestURL, "/api/mfa")
+ isSettingMFA := strings.HasPrefix(requestURL, "/cosmos-ui/loginmfa") || strings.HasPrefix(requestURL, "/cosmos-ui/newmfa") || strings.HasPrefix(requestURL, "/api/mfa")
userInBase.MFAState = 0
@@ -201,15 +201,15 @@ func logOutUser(w http.ResponseWriter, req *http.Request) {
}
func redirectToReLogin(w http.ResponseWriter, req *http.Request) {
- http.Redirect(w, req, "/ui/login?invalid=1&redirect=" + req.URL.Path + "&" + req.URL.RawQuery, http.StatusTemporaryRedirect)
+ http.Redirect(w, req, "/cosmos-ui/login?invalid=1&redirect=" + req.URL.Path + "&" + req.URL.RawQuery, http.StatusTemporaryRedirect)
}
func redirectToLoginMFA(w http.ResponseWriter, req *http.Request) {
- http.Redirect(w, req, "/ui/loginmfa?invalid=1&redirect=" + req.URL.Path + "&" + req.URL.RawQuery, http.StatusTemporaryRedirect)
+ http.Redirect(w, req, "/cosmos-ui/loginmfa?invalid=1&redirect=" + req.URL.Path + "&" + req.URL.RawQuery, http.StatusTemporaryRedirect)
}
func redirectToNewMFA(w http.ResponseWriter, req *http.Request) {
- http.Redirect(w, req, "/ui/newmfa?invalid=1&redirect=" + req.URL.Path + "&" + req.URL.RawQuery, http.StatusTemporaryRedirect)
+ http.Redirect(w, req, "/cosmos-ui/newmfa?invalid=1&redirect=" + req.URL.Path + "&" + req.URL.RawQuery, http.StatusTemporaryRedirect)
}
func SendUserToken(w http.ResponseWriter, req *http.Request, user utils.User, mfaDone bool) {
diff --git a/src/utils/loggedIn.go b/src/utils/loggedIn.go
index bbba933..5294e30 100644
--- a/src/utils/loggedIn.go
+++ b/src/utils/loggedIn.go
@@ -15,15 +15,15 @@ func LoggedInOnlyWithRedirect(w http.ResponseWriter, req *http.Request) error {
if !isUserLoggedIn || userNickname == "" {
Error("LoggedInOnlyWithRedirect: User is not logged in", nil)
- http.Redirect(w, req, "/ui/login?notlogged=1&redirect="+req.URL.Path, http.StatusFound)
+ http.Redirect(w, req, "/cosmos-ui/login?notlogged=1&redirect="+req.URL.Path, http.StatusFound)
return errors.New("User not logged in")
}
if(mfa == 1) {
- http.Redirect(w, req, "/ui/loginmfa?invalid=1&redirect=" + req.URL.Path + "&" + req.URL.RawQuery, http.StatusTemporaryRedirect)
+ http.Redirect(w, req, "/cosmos-ui/loginmfa?invalid=1&redirect=" + req.URL.Path + "&" + req.URL.RawQuery, http.StatusTemporaryRedirect)
return errors.New("User requires MFA")
} else if(mfa == 2) {
- http.Redirect(w, req, "/ui/newmfa?invalid=1&redirect=" + req.URL.Path + "&" + req.URL.RawQuery, http.StatusTemporaryRedirect)
+ http.Redirect(w, req, "/cosmos-ui/newmfa?invalid=1&redirect=" + req.URL.Path + "&" + req.URL.RawQuery, http.StatusTemporaryRedirect)
return errors.New("User requires MFA Setup")
}
@@ -39,7 +39,7 @@ func AdminOnlyWithRedirect(w http.ResponseWriter, req *http.Request) error {
if !isUserLoggedIn || userNickname == "" {
Error("AdminLoggedInOnlyWithRedirect: User is not logged in", nil)
- http.Redirect(w, req, "/ui/login?notlogged=1&redirect="+req.URL.Path, http.StatusFound)
+ http.Redirect(w, req, "/cosmos-ui/login?notlogged=1&redirect="+req.URL.Path, http.StatusFound)
return errors.New("User is not logged")
}
@@ -50,10 +50,10 @@ func AdminOnlyWithRedirect(w http.ResponseWriter, req *http.Request) error {
}
if(mfa == 1) {
- http.Redirect(w, req, "/ui/loginmfa?invalid=1&redirect=" + req.URL.Path + "&" + req.URL.RawQuery, http.StatusTemporaryRedirect)
+ http.Redirect(w, req, "/cosmos-ui/loginmfa?invalid=1&redirect=" + req.URL.Path + "&" + req.URL.RawQuery, http.StatusTemporaryRedirect)
return errors.New("User requires MFA")
} else if(mfa == 2) {
- http.Redirect(w, req, "/ui/newmfa?invalid=1&redirect=" + req.URL.Path + "&" + req.URL.RawQuery, http.StatusTemporaryRedirect)
+ http.Redirect(w, req, "/cosmos-ui/newmfa?invalid=1&redirect=" + req.URL.Path + "&" + req.URL.RawQuery, http.StatusTemporaryRedirect)
return errors.New("User requires MFA Setup")
}