Compare commits
48 Commits
fix/gatewa
...
feat/loggi
Author | SHA1 | Date | |
---|---|---|---|
![]() |
99dc5ee572 | ||
![]() |
8bee421d0a | ||
![]() |
714b79e4ab | ||
![]() |
d886d780b4 | ||
![]() |
d7bb10fd21 | ||
![]() |
f5515bec28 | ||
![]() |
b35d86fd40 | ||
![]() |
2c4bc9adb6 | ||
![]() |
5884802e60 | ||
![]() |
241f977b2a | ||
![]() |
ed855a274a | ||
![]() |
049ea64475 | ||
![]() |
5e4f34c889 | ||
![]() |
ab717d956a | ||
![]() |
6209c4d506 | ||
![]() |
2bc4c74930 | ||
![]() |
1efa419cdf | ||
![]() |
4ceb6db4ba | ||
![]() |
9edc8d0fb5 | ||
![]() |
da0fcb109b | ||
![]() |
3e51a7bd01 | ||
![]() |
28bed69b2e | ||
![]() |
0433d64737 | ||
![]() |
773213e5a4 | ||
![]() |
de44c40de5 | ||
![]() |
a7fa988bf0 | ||
![]() |
538a2d0b59 | ||
![]() |
f519f0eb0e | ||
![]() |
d5ad4a6e55 | ||
![]() |
d9b49ca932 | ||
![]() |
7c5aab7bf3 | ||
![]() |
c783e101d5 | ||
![]() |
ebccfb18cd | ||
![]() |
b7aeff57af | ||
![]() |
075c287f34 | ||
![]() |
4778827545 | ||
![]() |
39c2c364d9 | ||
![]() |
961f2271c1 | ||
![]() |
aaf0831793 | ||
![]() |
27cb41c54c | ||
![]() |
718b2d535f | ||
![]() |
ed6a1ceccc | ||
![]() |
fd52d6e5d3 | ||
![]() |
325aa88368 | ||
![]() |
75e44ff698 | ||
![]() |
d5f1c5a5eb | ||
![]() |
39947f1753 | ||
![]() |
a6b743465f |
@@ -9,3 +9,4 @@ build
|
|||||||
data.db
|
data.db
|
||||||
app/node_modules
|
app/node_modules
|
||||||
app/build
|
app/build
|
||||||
|
certs/
|
||||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@@ -13,4 +13,5 @@ data.db
|
|||||||
*.tar.gz
|
*.tar.gz
|
||||||
.vscode/
|
.vscode/
|
||||||
.yalc
|
.yalc
|
||||||
yalc.lock
|
yalc.lock
|
||||||
|
certs/
|
34
dashboard/package-lock.json
generated
34
dashboard/package-lock.json
generated
@@ -10,6 +10,7 @@
|
|||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@chakra-ui/react": "^1.7.3",
|
"@chakra-ui/react": "^1.7.3",
|
||||||
|
"@emotion/core": "^11.0.0",
|
||||||
"@emotion/react": "^11.7.1",
|
"@emotion/react": "^11.7.1",
|
||||||
"@emotion/styled": "^11.6.0",
|
"@emotion/styled": "^11.6.0",
|
||||||
"@types/react": "^17.0.38",
|
"@types/react": "^17.0.38",
|
||||||
@@ -17,6 +18,7 @@
|
|||||||
"@types/react-router-dom": "^5.3.2",
|
"@types/react-router-dom": "^5.3.2",
|
||||||
"dayjs": "^1.10.7",
|
"dayjs": "^1.10.7",
|
||||||
"esbuild": "^0.14.9",
|
"esbuild": "^0.14.9",
|
||||||
|
"focus-visible": "^5.2.0",
|
||||||
"framer-motion": "^5.5.5",
|
"framer-motion": "^5.5.5",
|
||||||
"graphql": "^16.2.0",
|
"graphql": "^16.2.0",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
@@ -978,6 +980,11 @@
|
|||||||
"stylis": "4.0.13"
|
"stylis": "4.0.13"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@emotion/core": {
|
||||||
|
"version": "11.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@emotion/core/-/core-11.0.0.tgz",
|
||||||
|
"integrity": "sha512-w4sE3AmHmyG6RDKf6mIbtHpgJUSJ2uGvPQb8VXFL7hFjMPibE8IiehG8cMX3Ztm4svfCQV6KqusQbeIOkurBcA=="
|
||||||
|
},
|
||||||
"node_modules/@emotion/hash": {
|
"node_modules/@emotion/hash": {
|
||||||
"version": "0.8.0",
|
"version": "0.8.0",
|
||||||
"resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz",
|
||||||
@@ -1667,6 +1674,11 @@
|
|||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/focus-visible": {
|
||||||
|
"version": "5.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/focus-visible/-/focus-visible-5.2.0.tgz",
|
||||||
|
"integrity": "sha512-Rwix9pBtC1Nuy5wysTmKy+UjbDJpIfg8eHjw0rjZ1mX4GNLz1Bmd16uDpI3Gk1i70Fgcs8Csg2lPm8HULFg9DQ=="
|
||||||
|
},
|
||||||
"node_modules/framer-motion": {
|
"node_modules/framer-motion": {
|
||||||
"version": "5.5.5",
|
"version": "5.5.5",
|
||||||
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-5.5.5.tgz",
|
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-5.5.5.tgz",
|
||||||
@@ -2517,8 +2529,7 @@
|
|||||||
"@chakra-ui/css-reset": {
|
"@chakra-ui/css-reset": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@chakra-ui/css-reset/-/css-reset-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@chakra-ui/css-reset/-/css-reset-1.1.1.tgz",
|
||||||
"integrity": "sha512-+KNNHL4OWqeKia5SL858K3Qbd8WxMij9mWIilBzLD4j2KFrl/+aWFw8syMKth3NmgIibrjsljo+PU3fy2o50dg==",
|
"integrity": "sha512-+KNNHL4OWqeKia5SL858K3Qbd8WxMij9mWIilBzLD4j2KFrl/+aWFw8syMKth3NmgIibrjsljo+PU3fy2o50dg=="
|
||||||
"requires": {}
|
|
||||||
},
|
},
|
||||||
"@chakra-ui/descendant": {
|
"@chakra-ui/descendant": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
@@ -3038,6 +3049,11 @@
|
|||||||
"stylis": "4.0.13"
|
"stylis": "4.0.13"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@emotion/core": {
|
||||||
|
"version": "11.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@emotion/core/-/core-11.0.0.tgz",
|
||||||
|
"integrity": "sha512-w4sE3AmHmyG6RDKf6mIbtHpgJUSJ2uGvPQb8VXFL7hFjMPibE8IiehG8cMX3Ztm4svfCQV6KqusQbeIOkurBcA=="
|
||||||
|
},
|
||||||
"@emotion/hash": {
|
"@emotion/hash": {
|
||||||
"version": "0.8.0",
|
"version": "0.8.0",
|
||||||
"resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz",
|
||||||
@@ -3117,8 +3133,7 @@
|
|||||||
"@graphql-typed-document-node/core": {
|
"@graphql-typed-document-node/core": {
|
||||||
"version": "3.1.1",
|
"version": "3.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.1.1.tgz",
|
||||||
"integrity": "sha512-NQ17ii0rK1b34VZonlmT2QMJFI70m0TRwbknO/ihlbatXyaktDhN/98vBiUU6kNBPljqGqyIrl2T4nY2RpFANg==",
|
"integrity": "sha512-NQ17ii0rK1b34VZonlmT2QMJFI70m0TRwbknO/ihlbatXyaktDhN/98vBiUU6kNBPljqGqyIrl2T4nY2RpFANg=="
|
||||||
"requires": {}
|
|
||||||
},
|
},
|
||||||
"@popperjs/core": {
|
"@popperjs/core": {
|
||||||
"version": "2.11.0",
|
"version": "2.11.0",
|
||||||
@@ -3540,6 +3555,11 @@
|
|||||||
"tslib": "^2.0.3"
|
"tslib": "^2.0.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"focus-visible": {
|
||||||
|
"version": "5.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/focus-visible/-/focus-visible-5.2.0.tgz",
|
||||||
|
"integrity": "sha512-Rwix9pBtC1Nuy5wysTmKy+UjbDJpIfg8eHjw0rjZ1mX4GNLz1Bmd16uDpI3Gk1i70Fgcs8Csg2lPm8HULFg9DQ=="
|
||||||
|
},
|
||||||
"framer-motion": {
|
"framer-motion": {
|
||||||
"version": "5.5.5",
|
"version": "5.5.5",
|
||||||
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-5.5.5.tgz",
|
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-5.5.5.tgz",
|
||||||
@@ -3823,8 +3843,7 @@
|
|||||||
"react-icons": {
|
"react-icons": {
|
||||||
"version": "4.3.1",
|
"version": "4.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.3.1.tgz",
|
||||||
"integrity": "sha512-cB10MXLTs3gVuXimblAdI71jrJx8njrJZmNMEMC+sQu5B/BIOmlsAjskdqpn81y8UBVEGuHODd7/ci5DvoSzTQ==",
|
"integrity": "sha512-cB10MXLTs3gVuXimblAdI71jrJx8njrJZmNMEMC+sQu5B/BIOmlsAjskdqpn81y8UBVEGuHODd7/ci5DvoSzTQ=="
|
||||||
"requires": {}
|
|
||||||
},
|
},
|
||||||
"react-is": {
|
"react-is": {
|
||||||
"version": "16.13.1",
|
"version": "16.13.1",
|
||||||
@@ -4010,8 +4029,7 @@
|
|||||||
"use-callback-ref": {
|
"use-callback-ref": {
|
||||||
"version": "1.2.5",
|
"version": "1.2.5",
|
||||||
"resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.2.5.tgz",
|
"resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.2.5.tgz",
|
||||||
"integrity": "sha512-gN3vgMISAgacF7sqsLPByqoePooY3n2emTH59Ur5d/M8eg4WTWu1xp8i8DHjohftIyEx0S08RiYxbffr4j8Peg==",
|
"integrity": "sha512-gN3vgMISAgacF7sqsLPByqoePooY3n2emTH59Ur5d/M8eg4WTWu1xp8i8DHjohftIyEx0S08RiYxbffr4j8Peg=="
|
||||||
"requires": {}
|
|
||||||
},
|
},
|
||||||
"use-sidecar": {
|
"use-sidecar": {
|
||||||
"version": "1.0.5",
|
"version": "1.0.5",
|
||||||
|
@@ -12,6 +12,7 @@
|
|||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@chakra-ui/react": "^1.7.3",
|
"@chakra-ui/react": "^1.7.3",
|
||||||
|
"@emotion/core": "^11.0.0",
|
||||||
"@emotion/react": "^11.7.1",
|
"@emotion/react": "^11.7.1",
|
||||||
"@emotion/styled": "^11.6.0",
|
"@emotion/styled": "^11.6.0",
|
||||||
"@types/react": "^17.0.38",
|
"@types/react": "^17.0.38",
|
||||||
@@ -19,6 +20,7 @@
|
|||||||
"@types/react-router-dom": "^5.3.2",
|
"@types/react-router-dom": "^5.3.2",
|
||||||
"dayjs": "^1.10.7",
|
"dayjs": "^1.10.7",
|
||||||
"esbuild": "^0.14.9",
|
"esbuild": "^0.14.9",
|
||||||
|
"focus-visible": "^5.2.0",
|
||||||
"framer-motion": "^5.5.5",
|
"framer-motion": "^5.5.5",
|
||||||
"graphql": "^16.2.0",
|
"graphql": "^16.2.0",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
import { Fragment } from 'react';
|
||||||
import { ChakraProvider, extendTheme } from '@chakra-ui/react';
|
import { ChakraProvider, extendTheme } from '@chakra-ui/react';
|
||||||
import { BrowserRouter } from 'react-router-dom';
|
import { BrowserRouter } from 'react-router-dom';
|
||||||
import { createClient, Provider } from 'urql';
|
import { createClient, Provider } from 'urql';
|
||||||
@@ -24,6 +25,7 @@ const theme = extendTheme({
|
|||||||
'html, body, #root': {
|
'html, body, #root': {
|
||||||
fontFamily: 'Avenir, Helvetica, Arial, sans-serif',
|
fontFamily: 'Avenir, Helvetica, Arial, sans-serif',
|
||||||
height: '100%',
|
height: '100%',
|
||||||
|
outline: 'none',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -36,14 +38,16 @@ const theme = extendTheme({
|
|||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
return (
|
return (
|
||||||
<ChakraProvider theme={theme}>
|
<Fragment>
|
||||||
<Provider value={queryClient}>
|
<ChakraProvider theme={theme}>
|
||||||
<BrowserRouter basename="/dashboard">
|
<Provider value={queryClient}>
|
||||||
<AuthContextProvider>
|
<BrowserRouter basename="/dashboard">
|
||||||
<AppRoutes />
|
<AuthContextProvider>
|
||||||
</AuthContextProvider>
|
<AppRoutes />
|
||||||
</BrowserRouter>
|
</AuthContextProvider>
|
||||||
</Provider>
|
</BrowserRouter>
|
||||||
</ChakraProvider>
|
</Provider>
|
||||||
|
</ChakraProvider>
|
||||||
|
</Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
65
dashboard/src/components/EnvComponents/AccessToken.tsx
Normal file
65
dashboard/src/components/EnvComponents/AccessToken.tsx
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { Flex, Stack, Text, useMediaQuery } from "@chakra-ui/react";
|
||||||
|
import InputField from "../../components/InputField";
|
||||||
|
import { TextInputType, TextAreaInputType } from "../../constants";
|
||||||
|
|
||||||
|
const AccessToken = ({ variables, setVariables }: any) => {
|
||||||
|
const [isNotSmallerScreen] = useMediaQuery("(min-width:600px)");
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{" "}
|
||||||
|
<Text fontSize="md" paddingTop="2%" fontWeight="bold" mb={5}>
|
||||||
|
Access Token
|
||||||
|
</Text>
|
||||||
|
<Stack spacing={6} padding="2% 0%">
|
||||||
|
<Flex direction={isNotSmallerScreen ? "row" : "column"}>
|
||||||
|
<Flex
|
||||||
|
w={isNotSmallerScreen ? "30%" : "50%"}
|
||||||
|
justifyContent="start"
|
||||||
|
alignItems="center"
|
||||||
|
>
|
||||||
|
<Text fontSize="sm">Access Token Expiry Time:</Text>
|
||||||
|
</Flex>
|
||||||
|
<Flex
|
||||||
|
w={isNotSmallerScreen ? "70%" : "100%"}
|
||||||
|
mt={isNotSmallerScreen ? "0" : "3"}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={5}
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={TextInputType.ACCESS_TOKEN_EXPIRY_TIME}
|
||||||
|
placeholder="0h15m0s"
|
||||||
|
/>
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
<Flex direction={isNotSmallerScreen ? "row" : "column"}>
|
||||||
|
<Flex
|
||||||
|
w={isNotSmallerScreen ? "30%" : "60%"}
|
||||||
|
justifyContent="start"
|
||||||
|
direction="column"
|
||||||
|
>
|
||||||
|
<Text fontSize="sm">Custom Scripts:</Text>
|
||||||
|
<Text fontSize="xs" color="blackAlpha.500">
|
||||||
|
(Used to add custom fields in ID token)
|
||||||
|
</Text>
|
||||||
|
</Flex>
|
||||||
|
<Flex
|
||||||
|
w={isNotSmallerScreen ? "70%" : "100%"}
|
||||||
|
mt={isNotSmallerScreen ? "0" : "3"}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={TextAreaInputType.CUSTOM_ACCESS_TOKEN_SCRIPT}
|
||||||
|
placeholder="Add script here"
|
||||||
|
minH="25vh"
|
||||||
|
/>
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
</Stack>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AccessToken;
|
@@ -0,0 +1,88 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { Flex, Stack, Center, Text, useMediaQuery } from "@chakra-ui/react";
|
||||||
|
|
||||||
|
import InputField from "../../components/InputField";
|
||||||
|
import { TextInputType } from "../../constants";
|
||||||
|
|
||||||
|
const DatabaseCredentials = ({ variables, setVariables }: any) => {
|
||||||
|
const [isNotSmallerScreen] = useMediaQuery("(min-width:600px)");
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{" "}
|
||||||
|
<Text fontSize="md" paddingTop="2%" fontWeight="bold">
|
||||||
|
Database Credentials
|
||||||
|
</Text>
|
||||||
|
<Stack spacing={6} padding="3% 0">
|
||||||
|
<Text fontStyle="italic" fontSize="sm" color="blackAlpha.500" mt={3}>
|
||||||
|
Note: Database related environment variables cannot be updated from
|
||||||
|
dashboard :(
|
||||||
|
</Text>
|
||||||
|
<Flex direction={isNotSmallerScreen ? "row" : "column"}>
|
||||||
|
<Flex
|
||||||
|
w={isNotSmallerScreen ? "30%" : "40%"}
|
||||||
|
justifyContent="start"
|
||||||
|
alignItems="center"
|
||||||
|
>
|
||||||
|
<Text fontSize="sm">DataBase Name:</Text>
|
||||||
|
</Flex>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? "70%" : "100%"}
|
||||||
|
mt={isNotSmallerScreen ? "0" : "3"}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={5}
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={TextInputType.DATABASE_NAME}
|
||||||
|
isDisabled={true}
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
<Flex direction={isNotSmallerScreen ? "row" : "column"}>
|
||||||
|
<Flex
|
||||||
|
w={isNotSmallerScreen ? "30%" : "40%"}
|
||||||
|
justifyContent="start"
|
||||||
|
alignItems="center"
|
||||||
|
>
|
||||||
|
<Text fontSize="sm">DataBase Type:</Text>
|
||||||
|
</Flex>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? "70%" : "100%"}
|
||||||
|
mt={isNotSmallerScreen ? "0" : "3"}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={5}
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={TextInputType.DATABASE_TYPE}
|
||||||
|
isDisabled={true}
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
<Flex direction={isNotSmallerScreen ? "row" : "column"}>
|
||||||
|
<Flex
|
||||||
|
w={isNotSmallerScreen ? "30%" : "40%"}
|
||||||
|
justifyContent="start"
|
||||||
|
alignItems="center"
|
||||||
|
>
|
||||||
|
<Text fontSize="sm">DataBase URL:</Text>
|
||||||
|
</Flex>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? "70%" : "100%"}
|
||||||
|
mt={isNotSmallerScreen ? "0" : "3"}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={5}
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={TextInputType.DATABASE_URL}
|
||||||
|
isDisabled={true}
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
</Stack>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DatabaseCredentials;
|
@@ -0,0 +1,35 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { Flex, Stack, Center, Text, useMediaQuery } from "@chakra-ui/react";
|
||||||
|
import InputField from "../../components/InputField";
|
||||||
|
import { ArrayInputType} from "../../constants";
|
||||||
|
|
||||||
|
const DomainWhiteListing = ({ variables, setVariables }: any) => {
|
||||||
|
const [isNotSmallerScreen] = useMediaQuery("(min-width:600px)");
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{" "}
|
||||||
|
<Text fontSize="md" paddingTop="2%" fontWeight="bold" mb={5}>
|
||||||
|
Domain White Listing
|
||||||
|
</Text>
|
||||||
|
<Stack spacing={6} padding="2% 0%">
|
||||||
|
<Flex direction={isNotSmallerScreen ? "row" : "column"}>
|
||||||
|
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||||
|
<Text fontSize="sm">Allowed Origins:</Text>
|
||||||
|
</Flex>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? "70%" : "100%"}
|
||||||
|
mt={isNotSmallerScreen ? "0" : "3"}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={ArrayInputType.ALLOWED_ORIGINS}
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
</Stack>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DomainWhiteListing;
|
114
dashboard/src/components/EnvComponents/EmailConfiguration.tsx
Normal file
114
dashboard/src/components/EnvComponents/EmailConfiguration.tsx
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { Flex, Stack, Center, Text, useMediaQuery } from "@chakra-ui/react";
|
||||||
|
import InputField from "../../components/InputField";
|
||||||
|
import { TextInputType, HiddenInputType} from "../../constants";
|
||||||
|
const EmailConfigurations = ({
|
||||||
|
variables,
|
||||||
|
setVariables,
|
||||||
|
fieldVisibility,
|
||||||
|
setFieldVisibility,
|
||||||
|
}: any) => {
|
||||||
|
const [isNotSmallerScreen] = useMediaQuery("(min-width:600px)");
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{" "}
|
||||||
|
<Text fontSize="md" paddingTop="2%" fontWeight="bold" mb={5}>
|
||||||
|
Email Configurations
|
||||||
|
</Text>
|
||||||
|
<Stack spacing={6} padding="2% 0%">
|
||||||
|
<Flex direction={isNotSmallerScreen ? "row" : "column"}>
|
||||||
|
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||||
|
<Text fontSize="sm">SMTP Host:</Text>
|
||||||
|
</Flex>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? "70%" : "100%"}
|
||||||
|
mt={isNotSmallerScreen ? "0" : "3"}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={5}
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={TextInputType.SMTP_HOST}
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
<Flex direction={isNotSmallerScreen ? "row" : "column"}>
|
||||||
|
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||||
|
<Text fontSize="sm">SMTP Port:</Text>
|
||||||
|
</Flex>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? "70%" : "100%"}
|
||||||
|
mt={isNotSmallerScreen ? "0" : "3"}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={5}
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={TextInputType.SMTP_PORT}
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
<Flex direction={isNotSmallerScreen ? "row" : "column"}>
|
||||||
|
<Flex
|
||||||
|
w={isNotSmallerScreen ? "30%" : "40%"}
|
||||||
|
justifyContent="start"
|
||||||
|
alignItems="center"
|
||||||
|
>
|
||||||
|
<Text fontSize="sm">SMTP Username:</Text>
|
||||||
|
</Flex>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? "70%" : "100%"}
|
||||||
|
mt={isNotSmallerScreen ? "0" : "3"}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={5}
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={TextInputType.SMTP_USERNAME}
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
<Flex direction={isNotSmallerScreen ? "row" : "column"}>
|
||||||
|
<Flex
|
||||||
|
w={isNotSmallerScreen ? "30%" : "40%"}
|
||||||
|
justifyContent="start"
|
||||||
|
alignItems="center"
|
||||||
|
>
|
||||||
|
<Text fontSize="sm">SMTP Password:</Text>
|
||||||
|
</Flex>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? "70%" : "100%"}
|
||||||
|
mt={isNotSmallerScreen ? "0" : "3"}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={5}
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
fieldVisibility={fieldVisibility}
|
||||||
|
setFieldVisibility={setFieldVisibility}
|
||||||
|
inputType={HiddenInputType.SMTP_PASSWORD}
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
<Flex direction={isNotSmallerScreen ? "row" : "column"}>
|
||||||
|
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||||
|
<Text fontSize="sm">From Email:</Text>
|
||||||
|
</Flex>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? "70%" : "100%"}
|
||||||
|
mt={isNotSmallerScreen ? "0" : "3"}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={5}
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={TextInputType.SENDER_EMAIL}
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
</Stack>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default EmailConfigurations;
|
154
dashboard/src/components/EnvComponents/JWTConfiguration.tsx
Normal file
154
dashboard/src/components/EnvComponents/JWTConfiguration.tsx
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { Flex, Stack, Center, Text, useMediaQuery } from "@chakra-ui/react";
|
||||||
|
import {
|
||||||
|
HiddenInputType,
|
||||||
|
TextInputType,
|
||||||
|
TextAreaInputType,
|
||||||
|
} from "../../constants";
|
||||||
|
import GenerateKeysModal from "../GenerateKeysModal";
|
||||||
|
import InputField from "../InputField";
|
||||||
|
|
||||||
|
const JSTConfigurations = ({
|
||||||
|
variables,
|
||||||
|
setVariables,
|
||||||
|
fieldVisibility,
|
||||||
|
setFieldVisibility,
|
||||||
|
SelectInputType,
|
||||||
|
getData,
|
||||||
|
HMACEncryptionType,
|
||||||
|
RSAEncryptionType,
|
||||||
|
ECDSAEncryptionType,
|
||||||
|
}: any) => {
|
||||||
|
const [isNotSmallerScreen] = useMediaQuery("(min-width:600px)");
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{" "}
|
||||||
|
<Flex
|
||||||
|
borderRadius={5}
|
||||||
|
width="100%"
|
||||||
|
justifyContent="space-between"
|
||||||
|
alignItems="center"
|
||||||
|
paddingTop="2%"
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
fontSize={isNotSmallerScreen ? "md" : "sm"}
|
||||||
|
fontWeight="bold"
|
||||||
|
mb={5}
|
||||||
|
>
|
||||||
|
JWT (JSON Web Tokens) Configurations
|
||||||
|
</Text>
|
||||||
|
<Flex mb={7}>
|
||||||
|
<GenerateKeysModal jwtType={variables.JWT_TYPE} getData={getData} />
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
<Stack spacing={6} padding="2% 0%">
|
||||||
|
<Flex direction={isNotSmallerScreen ? "row" : "column"}>
|
||||||
|
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||||
|
<Text fontSize="sm">JWT Type:</Text>
|
||||||
|
</Flex>
|
||||||
|
<Flex
|
||||||
|
w={isNotSmallerScreen ? "70%" : "100%"}
|
||||||
|
mt={isNotSmallerScreen ? "0" : "2"}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={5}
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={SelectInputType}
|
||||||
|
value={SelectInputType}
|
||||||
|
options={{
|
||||||
|
...HMACEncryptionType,
|
||||||
|
...RSAEncryptionType,
|
||||||
|
...ECDSAEncryptionType,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
{Object.values(HMACEncryptionType).includes(variables.JWT_TYPE) ? (
|
||||||
|
<Flex direction={isNotSmallerScreen ? "row" : "column"}>
|
||||||
|
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||||
|
<Text fontSize="sm">JWT Secret</Text>
|
||||||
|
</Flex>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? "70%" : "100%"}
|
||||||
|
mt={isNotSmallerScreen ? "0" : "2"}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={5}
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
fieldVisibility={fieldVisibility}
|
||||||
|
setFieldVisibility={setFieldVisibility}
|
||||||
|
inputType={HiddenInputType.JWT_SECRET}
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<Flex direction={isNotSmallerScreen ? "row" : "column"}>
|
||||||
|
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||||
|
<Text fontSize="sm">Public Key</Text>
|
||||||
|
</Flex>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? "70%" : "100%"}
|
||||||
|
mt={isNotSmallerScreen ? "0" : "2"}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={5}
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={TextAreaInputType.JWT_PUBLIC_KEY}
|
||||||
|
placeholder="Add public key here"
|
||||||
|
minH="25vh"
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
<Flex direction={isNotSmallerScreen ? "row" : "column"}>
|
||||||
|
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||||
|
<Text fontSize="sm">Private Key</Text>
|
||||||
|
</Flex>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? "70%" : "100%"}
|
||||||
|
mt={isNotSmallerScreen ? "0" : "2"}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={5}
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={TextAreaInputType.JWT_PRIVATE_KEY}
|
||||||
|
placeholder="Add private key here"
|
||||||
|
minH="25vh"
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
<Flex direction={isNotSmallerScreen ? "row" : "column"}>
|
||||||
|
<Flex
|
||||||
|
w={isNotSmallerScreen ? "30%" : "40%"}
|
||||||
|
justifyContent="start"
|
||||||
|
alignItems="center"
|
||||||
|
>
|
||||||
|
<Text fontSize="sm" orientation="vertical">
|
||||||
|
JWT Role Claim:
|
||||||
|
</Text>
|
||||||
|
</Flex>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? "70%" : "100%"}
|
||||||
|
mt={isNotSmallerScreen ? "0" : "2"}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={5}
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={TextInputType.JWT_ROLE_CLAIM}
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
</Stack>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default JSTConfigurations;
|
191
dashboard/src/components/EnvComponents/OAuthConfig.tsx
Normal file
191
dashboard/src/components/EnvComponents/OAuthConfig.tsx
Normal file
@@ -0,0 +1,191 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import InputField from '../InputField';
|
||||||
|
import {
|
||||||
|
Flex,
|
||||||
|
Stack,
|
||||||
|
Center,
|
||||||
|
Text,
|
||||||
|
Box,
|
||||||
|
Divider,
|
||||||
|
useMediaQuery,
|
||||||
|
} from '@chakra-ui/react';
|
||||||
|
import { FaGoogle, FaGithub, FaFacebookF } from 'react-icons/fa';
|
||||||
|
import { TextInputType, HiddenInputType } from '../../constants';
|
||||||
|
|
||||||
|
const OAuthConfig = ({
|
||||||
|
envVariables,
|
||||||
|
setVariables,
|
||||||
|
fieldVisibility,
|
||||||
|
setFieldVisibility,
|
||||||
|
}: any) => {
|
||||||
|
const [isNotSmallerScreen] = useMediaQuery('(min-width:667px)');
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Box>
|
||||||
|
<Text fontSize="md" paddingTop="2%" fontWeight="bold" mb={6}>
|
||||||
|
Your instance information
|
||||||
|
</Text>
|
||||||
|
<Stack spacing={6} padding="2% 0%">
|
||||||
|
<Flex direction={isNotSmallerScreen ? 'row' : 'column'}>
|
||||||
|
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||||
|
<Text fontSize="sm">Client ID</Text>
|
||||||
|
</Flex>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? '70%' : '100%'}
|
||||||
|
mt={isNotSmallerScreen ? '0' : '3'}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
variables={envVariables}
|
||||||
|
setVariables={() => {}}
|
||||||
|
inputType={TextInputType.CLIENT_ID}
|
||||||
|
placeholder="Client ID"
|
||||||
|
readOnly={true}
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
<Flex direction={isNotSmallerScreen ? 'row' : 'column'}>
|
||||||
|
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||||
|
<Text fontSize="sm">Client Secret</Text>
|
||||||
|
</Flex>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? '70%' : '100%'}
|
||||||
|
mt={isNotSmallerScreen ? '0' : '3'}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
variables={envVariables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
fieldVisibility={fieldVisibility}
|
||||||
|
setFieldVisibility={setFieldVisibility}
|
||||||
|
inputType={HiddenInputType.CLIENT_SECRET}
|
||||||
|
placeholder="Client Secret"
|
||||||
|
readOnly={true}
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
</Stack>
|
||||||
|
<Divider mt={5} mb={2} color="blackAlpha.700" />
|
||||||
|
<Text fontSize="md" paddingTop="2%" fontWeight="bold" mb={4}>
|
||||||
|
Social Media Logins
|
||||||
|
</Text>
|
||||||
|
<Stack spacing={6} padding="2% 0%">
|
||||||
|
<Flex direction={isNotSmallerScreen ? 'row' : 'column'}>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? '55px' : '35px'}
|
||||||
|
h="35px"
|
||||||
|
marginRight="1.5%"
|
||||||
|
border="1px solid #ff3e30"
|
||||||
|
borderRadius="5px"
|
||||||
|
>
|
||||||
|
<FaGoogle style={{ color: '#ff3e30' }} />
|
||||||
|
</Center>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? '70%' : '100%'}
|
||||||
|
mt={isNotSmallerScreen ? '0' : '3'}
|
||||||
|
marginRight="1.5%"
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={5}
|
||||||
|
variables={envVariables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={TextInputType.GOOGLE_CLIENT_ID}
|
||||||
|
placeholder="Google Client ID"
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? '70%' : '100%'}
|
||||||
|
mt={isNotSmallerScreen ? '0' : '3'}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={5}
|
||||||
|
variables={envVariables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
fieldVisibility={fieldVisibility}
|
||||||
|
setFieldVisibility={setFieldVisibility}
|
||||||
|
inputType={HiddenInputType.GOOGLE_CLIENT_SECRET}
|
||||||
|
placeholder="Google Secret"
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
<Flex direction={isNotSmallerScreen ? 'row' : 'column'}>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? '55px' : '35px'}
|
||||||
|
h="35px"
|
||||||
|
marginRight="1.5%"
|
||||||
|
border="1px solid #171515"
|
||||||
|
borderRadius="5px"
|
||||||
|
>
|
||||||
|
<FaGithub style={{ color: '#171515' }} />
|
||||||
|
</Center>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? '70%' : '100%'}
|
||||||
|
mt={isNotSmallerScreen ? '0' : '3'}
|
||||||
|
marginRight="1.5%"
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={5}
|
||||||
|
variables={envVariables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={TextInputType.GITHUB_CLIENT_ID}
|
||||||
|
placeholder="Github Client ID"
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? '70%' : '100%'}
|
||||||
|
mt={isNotSmallerScreen ? '0' : '3'}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={5}
|
||||||
|
variables={envVariables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
fieldVisibility={fieldVisibility}
|
||||||
|
setFieldVisibility={setFieldVisibility}
|
||||||
|
inputType={HiddenInputType.GITHUB_CLIENT_SECRET}
|
||||||
|
placeholder="Github Secret"
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
<Flex direction={isNotSmallerScreen ? 'row' : 'column'}>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? '55px' : '35px'}
|
||||||
|
h="35px"
|
||||||
|
marginRight="1.5%"
|
||||||
|
border="1px solid #3b5998"
|
||||||
|
borderRadius="5px"
|
||||||
|
>
|
||||||
|
<FaFacebookF style={{ color: '#3b5998' }} />
|
||||||
|
</Center>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? '70%' : '100%'}
|
||||||
|
mt={isNotSmallerScreen ? '0' : '3'}
|
||||||
|
marginRight="1.5%"
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={5}
|
||||||
|
variables={envVariables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={TextInputType.FACEBOOK_CLIENT_ID}
|
||||||
|
placeholder="Facebook Client ID"
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? '70%' : '100%'}
|
||||||
|
mt={isNotSmallerScreen ? '0' : '3'}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={5}
|
||||||
|
variables={envVariables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
fieldVisibility={fieldVisibility}
|
||||||
|
setFieldVisibility={setFieldVisibility}
|
||||||
|
inputType={HiddenInputType.FACEBOOK_CLIENT_SECRET}
|
||||||
|
placeholder="Facebook Secret"
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
</Stack>
|
||||||
|
</Box>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default OAuthConfig;
|
60
dashboard/src/components/EnvComponents/OrganizationInfo.tsx
Normal file
60
dashboard/src/components/EnvComponents/OrganizationInfo.tsx
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { Flex, Stack, Center, Text, useMediaQuery } from "@chakra-ui/react";
|
||||||
|
import InputField from "../InputField";
|
||||||
|
import { TextInputType } from "../../constants";
|
||||||
|
|
||||||
|
const OrganizationInfo = ({ variables, setVariables }: any) => {
|
||||||
|
const [isNotSmallerScreen] = useMediaQuery("(min-width:600px)");
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{" "}
|
||||||
|
<Text fontSize="md" paddingTop="2%" fontWeight="bold" mb={5}>
|
||||||
|
Organization Information
|
||||||
|
</Text>
|
||||||
|
<Stack spacing={6} padding="2% 0%">
|
||||||
|
<Flex direction={isNotSmallerScreen ? "row" : "column"}>
|
||||||
|
<Flex
|
||||||
|
w={isNotSmallerScreen ? "30%" : "40%"}
|
||||||
|
justifyContent="start"
|
||||||
|
alignItems="center"
|
||||||
|
>
|
||||||
|
<Text fontSize="sm">Organization Name:</Text>
|
||||||
|
</Flex>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? "70%" : "100%"}
|
||||||
|
mt={isNotSmallerScreen ? "0" : "3"}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={5}
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={TextInputType.ORGANIZATION_NAME}
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
<Flex direction={isNotSmallerScreen ? "row" : "column"}>
|
||||||
|
<Flex
|
||||||
|
w={isNotSmallerScreen ? "30%" : "40%"}
|
||||||
|
justifyContent="start"
|
||||||
|
alignItems="center"
|
||||||
|
>
|
||||||
|
<Text fontSize="sm">Organization Logo:</Text>
|
||||||
|
</Flex>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? "70%" : "100%"}
|
||||||
|
mt={isNotSmallerScreen ? "0" : "3"}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={5}
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={TextInputType.ORGANIZATION_LOGO}
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
</Stack>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default OrganizationInfo;
|
67
dashboard/src/components/EnvComponents/Roles.tsx
Normal file
67
dashboard/src/components/EnvComponents/Roles.tsx
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { Flex, Stack, Center, Text, useMediaQuery } from "@chakra-ui/react";
|
||||||
|
import { ArrayInputType } from "../../constants";
|
||||||
|
import InputField from "../InputField";
|
||||||
|
|
||||||
|
const Roles = ({ variables, setVariables }: any) => {
|
||||||
|
const [isNotSmallerScreen] = useMediaQuery("(min-width:600px)");
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{" "}
|
||||||
|
<Text fontSize="md" paddingTop="2%" fontWeight="bold" mb={5}>
|
||||||
|
Roles
|
||||||
|
</Text>
|
||||||
|
<Stack spacing={6} padding="2% 0%">
|
||||||
|
<Flex direction={isNotSmallerScreen ? "row" : "column"}>
|
||||||
|
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||||
|
<Text fontSize="sm">Roles:</Text>
|
||||||
|
</Flex>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? "70%" : "100%"}
|
||||||
|
mt={isNotSmallerScreen ? "0" : "2"}
|
||||||
|
overflow="hidden"
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={7}
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={ArrayInputType.ROLES}
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
<Flex direction={isNotSmallerScreen ? "row" : "column"}>
|
||||||
|
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||||
|
<Text fontSize="sm">Default Roles:</Text>
|
||||||
|
</Flex>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? "70%" : "100%"}
|
||||||
|
mt={isNotSmallerScreen ? "0" : "2"}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={ArrayInputType.DEFAULT_ROLES}
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
<Flex direction={isNotSmallerScreen ? "row" : "column"}>
|
||||||
|
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||||
|
<Text fontSize="sm">Protected Roles:</Text>
|
||||||
|
</Flex>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? "70%" : "100%"}
|
||||||
|
mt={isNotSmallerScreen ? "0" : "2"}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={ArrayInputType.PROTECTED_ROLES}
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
</Stack>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Roles;
|
138
dashboard/src/components/EnvComponents/SecurityAdminSecret.tsx
Normal file
138
dashboard/src/components/EnvComponents/SecurityAdminSecret.tsx
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
import React from "react";
|
||||||
|
import {
|
||||||
|
Flex,
|
||||||
|
Stack,
|
||||||
|
Center,
|
||||||
|
Text,
|
||||||
|
Input,
|
||||||
|
InputGroup,
|
||||||
|
InputRightElement,
|
||||||
|
useMediaQuery,
|
||||||
|
} from "@chakra-ui/react";
|
||||||
|
import { FaRegEyeSlash, FaRegEye } from "react-icons/fa";
|
||||||
|
import InputField from "../InputField";
|
||||||
|
import { HiddenInputType } from "../../constants";
|
||||||
|
const SecurityAdminSecret = ({
|
||||||
|
variables,
|
||||||
|
setVariables,
|
||||||
|
fieldVisibility,
|
||||||
|
setFieldVisibility,
|
||||||
|
validateAdminSecretHandler,
|
||||||
|
adminSecret,
|
||||||
|
}: any) => {
|
||||||
|
const [isNotSmallerScreen] = useMediaQuery("(min-width:600px)");
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{" "}
|
||||||
|
<Text fontSize="md" paddingTop="2%" fontWeight="bold">
|
||||||
|
Security (Admin Secret)
|
||||||
|
</Text>
|
||||||
|
<Stack
|
||||||
|
spacing={6}
|
||||||
|
padding="0 5%"
|
||||||
|
marginTop="3%"
|
||||||
|
border="1px solid #ff7875"
|
||||||
|
borderRadius="5px"
|
||||||
|
>
|
||||||
|
<Flex
|
||||||
|
marginTop={isNotSmallerScreen ? "3%" : "5%"}
|
||||||
|
direction={isNotSmallerScreen ? "row" : "column"}
|
||||||
|
>
|
||||||
|
<Flex
|
||||||
|
mt={3}
|
||||||
|
w={isNotSmallerScreen ? "30%" : "40%"}
|
||||||
|
justifyContent="start"
|
||||||
|
alignItems="center"
|
||||||
|
>
|
||||||
|
<Text fontSize="sm">Old Admin Secret:</Text>
|
||||||
|
</Flex>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? "70%" : "100%"}
|
||||||
|
mt={isNotSmallerScreen ? "0" : "3"}
|
||||||
|
>
|
||||||
|
<InputGroup size="sm">
|
||||||
|
<Input
|
||||||
|
borderRadius={5}
|
||||||
|
size="sm"
|
||||||
|
placeholder="Enter Old Admin Secret"
|
||||||
|
value={adminSecret.value as string}
|
||||||
|
onChange={(event: any) => validateAdminSecretHandler(event)}
|
||||||
|
type={
|
||||||
|
!fieldVisibility[HiddenInputType.OLD_ADMIN_SECRET]
|
||||||
|
? "password"
|
||||||
|
: "text"
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<InputRightElement
|
||||||
|
right="5px"
|
||||||
|
children={
|
||||||
|
<Flex>
|
||||||
|
{fieldVisibility[HiddenInputType.OLD_ADMIN_SECRET] ? (
|
||||||
|
<Center
|
||||||
|
w="25px"
|
||||||
|
margin="0 1.5%"
|
||||||
|
cursor="pointer"
|
||||||
|
onClick={() =>
|
||||||
|
setFieldVisibility({
|
||||||
|
...fieldVisibility,
|
||||||
|
[HiddenInputType.OLD_ADMIN_SECRET]: false,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<FaRegEyeSlash color="#bfbfbf" />
|
||||||
|
</Center>
|
||||||
|
) : (
|
||||||
|
<Center
|
||||||
|
w="25px"
|
||||||
|
margin="0 1.5%"
|
||||||
|
cursor="pointer"
|
||||||
|
onClick={() =>
|
||||||
|
setFieldVisibility({
|
||||||
|
...fieldVisibility,
|
||||||
|
[HiddenInputType.OLD_ADMIN_SECRET]: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<FaRegEye color="#bfbfbf" />
|
||||||
|
</Center>
|
||||||
|
)}
|
||||||
|
</Flex>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</InputGroup>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
<Flex
|
||||||
|
paddingBottom="3%"
|
||||||
|
direction={isNotSmallerScreen ? "row" : "column"}
|
||||||
|
>
|
||||||
|
<Flex
|
||||||
|
w={isNotSmallerScreen ? "30%" : "50%"}
|
||||||
|
justifyContent="start"
|
||||||
|
alignItems="center"
|
||||||
|
>
|
||||||
|
<Text fontSize="sm">New Admin Secret:</Text>
|
||||||
|
</Flex>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? "70%" : "100%"}
|
||||||
|
mt={isNotSmallerScreen ? "0" : "3"}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={5}
|
||||||
|
mb={3}
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={HiddenInputType.ADMIN_SECRET}
|
||||||
|
fieldVisibility={fieldVisibility}
|
||||||
|
setFieldVisibility={setFieldVisibility}
|
||||||
|
isDisabled={adminSecret.disableInputField}
|
||||||
|
placeholder="Enter New Admin Secret"
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
</Stack>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SecurityAdminSecret;
|
36
dashboard/src/components/EnvComponents/SessionStorage.tsx
Normal file
36
dashboard/src/components/EnvComponents/SessionStorage.tsx
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { Flex, Stack, Center, Text, useMediaQuery } from "@chakra-ui/react";
|
||||||
|
import InputField from "../InputField";
|
||||||
|
|
||||||
|
const SessionStorage = ({ variables, setVariables, RedisURL }: any) => {
|
||||||
|
const [isNotSmallerScreen] = useMediaQuery("(min-width:600px)");
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{" "}
|
||||||
|
<Text fontSize="md" paddingTop="2%" fontWeight="bold" mb={5}>
|
||||||
|
Session Storage
|
||||||
|
</Text>
|
||||||
|
<Stack spacing={6} padding="2% 0%">
|
||||||
|
<Flex direction={isNotSmallerScreen ? "row" : "column"}>
|
||||||
|
<Flex w="30%" justifyContent="start" alignItems="center">
|
||||||
|
<Text fontSize="sm">Redis URL:</Text>
|
||||||
|
</Flex>
|
||||||
|
<Center
|
||||||
|
w={isNotSmallerScreen ? "70%" : "100%"}
|
||||||
|
mt={isNotSmallerScreen ? "0" : "3"}
|
||||||
|
>
|
||||||
|
<InputField
|
||||||
|
borderRadius={5}
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={RedisURL}
|
||||||
|
placeholder="Redis URL"
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
</Flex>
|
||||||
|
</Stack>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SessionStorage;
|
79
dashboard/src/components/EnvComponents/UICustomization.tsx
Normal file
79
dashboard/src/components/EnvComponents/UICustomization.tsx
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Flex, Stack, Text } from '@chakra-ui/react';
|
||||||
|
import InputField from '../InputField';
|
||||||
|
import { SwitchInputType } from '../../constants';
|
||||||
|
|
||||||
|
const UICustomization = ({ variables, setVariables }: any) => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{' '}
|
||||||
|
<Text fontSize="md" paddingTop="2%" fontWeight="bold" mb={5}>
|
||||||
|
Disable Features
|
||||||
|
</Text>
|
||||||
|
<Stack spacing={6} padding="2% 0%">
|
||||||
|
<Flex>
|
||||||
|
<Flex w="100%" justifyContent="start" alignItems="center">
|
||||||
|
<Text fontSize="sm">Disable Login Page:</Text>
|
||||||
|
</Flex>
|
||||||
|
<Flex justifyContent="start">
|
||||||
|
<InputField
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={SwitchInputType.DISABLE_LOGIN_PAGE}
|
||||||
|
/>
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
<Flex>
|
||||||
|
<Flex w="100%" justifyContent="start" alignItems="center">
|
||||||
|
<Text fontSize="sm">Disable Email Verification:</Text>
|
||||||
|
</Flex>
|
||||||
|
<Flex justifyContent="start">
|
||||||
|
<InputField
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={SwitchInputType.DISABLE_EMAIL_VERIFICATION}
|
||||||
|
/>
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
<Flex>
|
||||||
|
<Flex w="100%" justifyContent="start" alignItems="center">
|
||||||
|
<Text fontSize="sm">Disable Magic Login Link:</Text>
|
||||||
|
</Flex>
|
||||||
|
<Flex justifyContent="start">
|
||||||
|
<InputField
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={SwitchInputType.DISABLE_MAGIC_LINK_LOGIN}
|
||||||
|
/>
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
<Flex>
|
||||||
|
<Flex w="100%" justifyContent="start" alignItems="center">
|
||||||
|
<Text fontSize="sm">Disable Basic Authentication:</Text>
|
||||||
|
</Flex>
|
||||||
|
<Flex justifyContent="start">
|
||||||
|
<InputField
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={SwitchInputType.DISABLE_BASIC_AUTHENTICATION}
|
||||||
|
/>
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
<Flex>
|
||||||
|
<Flex w="100%" justifyContent="start" alignItems="center">
|
||||||
|
<Text fontSize="sm">Disable Sign Up:</Text>
|
||||||
|
</Flex>
|
||||||
|
<Flex justifyContent="start" mb={3}>
|
||||||
|
<InputField
|
||||||
|
variables={variables}
|
||||||
|
setVariables={setVariables}
|
||||||
|
inputType={SwitchInputType.DISABLE_SIGN_UP}
|
||||||
|
/>
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
</Stack>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default UICustomization;
|
@@ -116,7 +116,7 @@ const InputField = ({
|
|||||||
<InputGroup size="sm">
|
<InputGroup size="sm">
|
||||||
<Input
|
<Input
|
||||||
{...props}
|
{...props}
|
||||||
value={variables[inputType]}
|
value={variables[inputType] ?? ''}
|
||||||
onChange={(
|
onChange={(
|
||||||
event: Event & {
|
event: Event & {
|
||||||
target: HTMLInputElement;
|
target: HTMLInputElement;
|
||||||
@@ -179,13 +179,14 @@ const InputField = ({
|
|||||||
if (Object.values(ArrayInputType).includes(inputType)) {
|
if (Object.values(ArrayInputType).includes(inputType)) {
|
||||||
return (
|
return (
|
||||||
<Flex
|
<Flex
|
||||||
border="1px solid #e2e8f0"
|
border="1px solid #e2e8f0"
|
||||||
w="100%"
|
w="100%"
|
||||||
paddingTop="0.5%"
|
borderRadius={5}
|
||||||
overflowX="scroll"
|
paddingTop="0.5%"
|
||||||
overflowY="hidden"
|
overflowX={variables[inputType].length > 3 ? "scroll" : "hidden"}
|
||||||
justifyContent="start"
|
overflowY="hidden"
|
||||||
alignItems="center"
|
justifyContent="start"
|
||||||
|
alignItems="center"
|
||||||
>
|
>
|
||||||
{variables[inputType].map((role: string, index: number) => (
|
{variables[inputType].map((role: string, index: number) => (
|
||||||
<Box key={index} margin="0.5%" role="group">
|
<Box key={index} margin="0.5%" role="group">
|
||||||
@@ -220,7 +221,7 @@ const InputField = ({
|
|||||||
size="xs"
|
size="xs"
|
||||||
minW="150px"
|
minW="150px"
|
||||||
placeholder="add a new value"
|
placeholder="add a new value"
|
||||||
value={inputData[inputType]}
|
value={inputData[inputType] ?? ''}
|
||||||
onChange={(e: any) => {
|
onChange={(e: any) => {
|
||||||
setInputData({ ...inputData, [inputType]: e.target.value });
|
setInputData({ ...inputData, [inputType]: e.target.value });
|
||||||
}}
|
}}
|
||||||
|
@@ -22,6 +22,7 @@ import {
|
|||||||
InputRightElement,
|
InputRightElement,
|
||||||
Text,
|
Text,
|
||||||
Link,
|
Link,
|
||||||
|
Tooltip
|
||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
import { useClient } from 'urql';
|
import { useClient } from 'urql';
|
||||||
import { FaUserPlus, FaMinusCircle, FaPlus, FaUpload } from 'react-icons/fa';
|
import { FaUserPlus, FaMinusCircle, FaPlus, FaUpload } from 'react-icons/fa';
|
||||||
@@ -186,7 +187,22 @@ const InviteMembersModal = ({
|
|||||||
isDisabled={disabled}
|
isDisabled={disabled}
|
||||||
size="sm"
|
size="sm"
|
||||||
>
|
>
|
||||||
<Center h="100%">Invite Members</Center>
|
<Center h="100%">
|
||||||
|
{disabled ? (
|
||||||
|
<Tooltip
|
||||||
|
mr={8}
|
||||||
|
mt={1}
|
||||||
|
hasArrow
|
||||||
|
bg="gray.300"
|
||||||
|
color="black"
|
||||||
|
label="Email verification is disabled, refer to 'UI Customization' tab within 'Environment' to enable it."
|
||||||
|
>
|
||||||
|
Invite Members
|
||||||
|
</Tooltip>
|
||||||
|
) : (
|
||||||
|
"Invite Members"
|
||||||
|
)}
|
||||||
|
</Center>{" "}
|
||||||
</Button>
|
</Button>
|
||||||
<Modal isOpen={isOpen} onClose={closeModalHandler} size="xl">
|
<Modal isOpen={isOpen} onClose={closeModalHandler} size="xl">
|
||||||
<ModalOverlay />
|
<ModalOverlay />
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import React, { ReactNode } from 'react';
|
import React, { Fragment, ReactNode } from 'react';
|
||||||
import {
|
import {
|
||||||
IconButton,
|
IconButton,
|
||||||
Box,
|
Box,
|
||||||
@@ -17,16 +17,27 @@ import {
|
|||||||
MenuButton,
|
MenuButton,
|
||||||
MenuItem,
|
MenuItem,
|
||||||
MenuList,
|
MenuList,
|
||||||
|
Accordion,
|
||||||
|
AccordionButton,
|
||||||
|
AccordionPanel,
|
||||||
|
AccordionItem,
|
||||||
|
useMediaQuery,
|
||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
import {
|
import {
|
||||||
FiHome,
|
FiUser,
|
||||||
FiCode,
|
FiCode,
|
||||||
FiSettings,
|
FiSettings,
|
||||||
FiMenu,
|
FiMenu,
|
||||||
FiUser,
|
|
||||||
FiUsers,
|
FiUsers,
|
||||||
FiChevronDown,
|
FiChevronDown,
|
||||||
} from 'react-icons/fi';
|
} from 'react-icons/fi';
|
||||||
|
import { BiCustomize } from 'react-icons/bi';
|
||||||
|
import { AiOutlineKey } from 'react-icons/ai';
|
||||||
|
import { SiOpenaccess, SiJsonwebtokens } from 'react-icons/si';
|
||||||
|
import { MdSecurity } from 'react-icons/md';
|
||||||
|
import { RiDatabase2Line } from 'react-icons/ri';
|
||||||
|
import { BsCheck2Circle } from 'react-icons/bs';
|
||||||
|
import { HiOutlineMail, HiOutlineOfficeBuilding } from 'react-icons/hi';
|
||||||
import { IconType } from 'react-icons';
|
import { IconType } from 'react-icons';
|
||||||
import { ReactText } from 'react';
|
import { ReactText } from 'react';
|
||||||
import { useMutation, useQuery } from 'urql';
|
import { useMutation, useQuery } from 'urql';
|
||||||
@@ -35,14 +46,70 @@ import { useAuthContext } from '../contexts/AuthContext';
|
|||||||
import { AdminLogout } from '../graphql/mutation';
|
import { AdminLogout } from '../graphql/mutation';
|
||||||
import { MetaQuery } from '../graphql/queries';
|
import { MetaQuery } from '../graphql/queries';
|
||||||
|
|
||||||
interface LinkItemProps {
|
interface SubRoutes {
|
||||||
name: string;
|
name: string;
|
||||||
icon: IconType;
|
icon: IconType;
|
||||||
route: string;
|
route: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface LinkItemProps {
|
||||||
|
name: string;
|
||||||
|
icon: IconType;
|
||||||
|
route: string;
|
||||||
|
subRoutes?: SubRoutes[];
|
||||||
|
}
|
||||||
const LinkItems: Array<LinkItemProps> = [
|
const LinkItems: Array<LinkItemProps> = [
|
||||||
// { name: 'Home', icon: FiHome, route: '/' },
|
{
|
||||||
{ name: 'Environment Variables', icon: FiSettings, route: '/' },
|
name: 'Environment ',
|
||||||
|
icon: FiSettings,
|
||||||
|
route: '/',
|
||||||
|
subRoutes: [
|
||||||
|
{
|
||||||
|
name: 'OAuth Config',
|
||||||
|
icon: AiOutlineKey,
|
||||||
|
route: '/oauth-setting',
|
||||||
|
},
|
||||||
|
|
||||||
|
{ name: 'Roles', icon: FiUser, route: '/roles' },
|
||||||
|
{
|
||||||
|
name: 'JWT Secrets',
|
||||||
|
icon: SiJsonwebtokens,
|
||||||
|
route: '/jwt-config',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Session Storage',
|
||||||
|
icon: RiDatabase2Line,
|
||||||
|
route: '/session-storage',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Email Configurations',
|
||||||
|
icon: HiOutlineMail,
|
||||||
|
route: '/email-config',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Domain White Listing',
|
||||||
|
icon: BsCheck2Circle,
|
||||||
|
route: '/whitelist-variables',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Organization Info',
|
||||||
|
icon: HiOutlineOfficeBuilding,
|
||||||
|
route: '/organization-info',
|
||||||
|
},
|
||||||
|
{ name: 'Access Token', icon: SiOpenaccess, route: '/access-token' },
|
||||||
|
{
|
||||||
|
name: 'UI Customization',
|
||||||
|
icon: BiCustomize,
|
||||||
|
route: '/ui-customization',
|
||||||
|
},
|
||||||
|
{ name: 'Database', icon: RiDatabase2Line, route: '/db-cred' },
|
||||||
|
{
|
||||||
|
name: ' Security',
|
||||||
|
icon: MdSecurity,
|
||||||
|
route: '/admin-secret',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
{ name: 'Users', icon: FiUsers, route: '/users' },
|
{ name: 'Users', icon: FiUsers, route: '/users' },
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -53,6 +120,7 @@ interface SidebarProps extends BoxProps {
|
|||||||
export const Sidebar = ({ onClose, ...rest }: SidebarProps) => {
|
export const Sidebar = ({ onClose, ...rest }: SidebarProps) => {
|
||||||
const { pathname } = useLocation();
|
const { pathname } = useLocation();
|
||||||
const [{ fetching, data }] = useQuery({ query: MetaQuery });
|
const [{ fetching, data }] = useQuery({ query: MetaQuery });
|
||||||
|
const [isNotSmallerScreen] = useMediaQuery('(min-width:600px)');
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
transition="3s ease"
|
transition="3s ease"
|
||||||
@@ -64,9 +132,15 @@ export const Sidebar = ({ onClose, ...rest }: SidebarProps) => {
|
|||||||
h="full"
|
h="full"
|
||||||
{...rest}
|
{...rest}
|
||||||
>
|
>
|
||||||
<Flex h="20" alignItems="center" mx="8" justifyContent="space-between">
|
<Flex
|
||||||
|
h="20"
|
||||||
|
alignItems="center"
|
||||||
|
mx="18"
|
||||||
|
justifyContent="space-between"
|
||||||
|
flexDirection="column"
|
||||||
|
>
|
||||||
<NavLink to="/">
|
<NavLink to="/">
|
||||||
<Flex alignItems="center">
|
<Flex alignItems="center" mt="6">
|
||||||
<Image
|
<Image
|
||||||
src="https://authorizer.dev/images/logo.png"
|
src="https://authorizer.dev/images/logo.png"
|
||||||
alt="logo"
|
alt="logo"
|
||||||
@@ -79,39 +153,96 @@ export const Sidebar = ({ onClose, ...rest }: SidebarProps) => {
|
|||||||
</NavLink>
|
</NavLink>
|
||||||
<CloseButton display={{ base: 'flex', md: 'none' }} onClick={onClose} />
|
<CloseButton display={{ base: 'flex', md: 'none' }} onClick={onClose} />
|
||||||
</Flex>
|
</Flex>
|
||||||
{LinkItems.map((link) => (
|
|
||||||
<NavLink key={link.name} to={link.route}>
|
|
||||||
<NavItem
|
|
||||||
icon={link.icon}
|
|
||||||
color={pathname === link.route ? 'blue.500' : ''}
|
|
||||||
>
|
|
||||||
{link.name}
|
|
||||||
</NavItem>
|
|
||||||
</NavLink>
|
|
||||||
))}
|
|
||||||
|
|
||||||
<Link
|
<Accordion defaultIndex={[0]} allowMultiple>
|
||||||
href="/playground"
|
<AccordionItem textAlign="center" border="none" w="100%">
|
||||||
target="_blank"
|
{LinkItems.map((link) =>
|
||||||
style={{
|
link?.subRoutes ? (
|
||||||
textDecoration: 'none',
|
<div key={link.name}>
|
||||||
}}
|
<AccordionButton _focus={{ boxShadow: 'none' }}>
|
||||||
_focus={{ _boxShadow: 'none' }}
|
<Text as="div" fontSize="md">
|
||||||
>
|
<NavItem
|
||||||
<NavItem icon={FiCode}>API Playground</NavItem>
|
icon={link.icon}
|
||||||
</Link>
|
color={pathname === link.route ? 'blue.500' : ''}
|
||||||
|
style={{ outline: 'unset' }}
|
||||||
|
height={12}
|
||||||
|
ml={-1}
|
||||||
|
mb={isNotSmallerScreen ? -1 : -4}
|
||||||
|
w={isNotSmallerScreen ? '100%' : '310%'}
|
||||||
|
>
|
||||||
|
<Fragment>
|
||||||
|
{link.name}
|
||||||
|
<Box display={{ base: 'none', md: 'flex' }} ml={12}>
|
||||||
|
<FiChevronDown />
|
||||||
|
</Box>
|
||||||
|
</Fragment>
|
||||||
|
</NavItem>
|
||||||
|
</Text>
|
||||||
|
</AccordionButton>
|
||||||
|
<AccordionPanel>
|
||||||
|
{link.subRoutes?.map((sublink) => (
|
||||||
|
<NavLink
|
||||||
|
key={sublink.name}
|
||||||
|
to={sublink.route}
|
||||||
|
onClick={onClose}
|
||||||
|
>
|
||||||
|
{' '}
|
||||||
|
<Text as="div" fontSize="xs" ml={2}>
|
||||||
|
<NavItem
|
||||||
|
icon={sublink.icon}
|
||||||
|
color={pathname === sublink.route ? 'blue.500' : ''}
|
||||||
|
height={8}
|
||||||
|
>
|
||||||
|
{sublink.name}
|
||||||
|
</NavItem>{' '}
|
||||||
|
</Text>
|
||||||
|
</NavLink>
|
||||||
|
))}
|
||||||
|
</AccordionPanel>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<NavLink key={link.name} to={link.route}>
|
||||||
|
{' '}
|
||||||
|
<Text as="div" fontSize="md" w="100%" mt={-2}>
|
||||||
|
<NavItem
|
||||||
|
icon={link.icon}
|
||||||
|
color={pathname === link.route ? 'blue.500' : ''}
|
||||||
|
height={12}
|
||||||
|
onClick={onClose}
|
||||||
|
>
|
||||||
|
{link.name}
|
||||||
|
</NavItem>{' '}
|
||||||
|
</Text>
|
||||||
|
</NavLink>
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
<Link
|
||||||
|
href="/playground"
|
||||||
|
target="_blank"
|
||||||
|
style={{
|
||||||
|
textDecoration: 'none',
|
||||||
|
}}
|
||||||
|
_focus={{ _boxShadow: 'none' }}
|
||||||
|
>
|
||||||
|
<NavItem icon={FiCode}>API Playground</NavItem>
|
||||||
|
</Link>
|
||||||
|
</AccordionItem>
|
||||||
|
</Accordion>
|
||||||
|
|
||||||
{data?.meta?.version && (
|
{data?.meta?.version && (
|
||||||
<Text
|
<Flex alignContent="center">
|
||||||
color="gray.600"
|
{' '}
|
||||||
fontSize="sm"
|
<Text
|
||||||
textAlign="center"
|
color="gray.400"
|
||||||
position="absolute"
|
fontSize="sm"
|
||||||
bottom="5"
|
textAlign="center"
|
||||||
left="7"
|
position="absolute"
|
||||||
>
|
bottom="5"
|
||||||
Current Version: {data.meta.version}
|
left="7"
|
||||||
</Text>
|
>
|
||||||
|
Current Version: {data.meta.version}
|
||||||
|
</Text>
|
||||||
|
</Flex>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
@@ -119,7 +250,7 @@ export const Sidebar = ({ onClose, ...rest }: SidebarProps) => {
|
|||||||
|
|
||||||
interface NavItemProps extends FlexProps {
|
interface NavItemProps extends FlexProps {
|
||||||
icon: IconType;
|
icon: IconType;
|
||||||
children: ReactText;
|
children: ReactText | JSX.Element | JSX.Element[];
|
||||||
}
|
}
|
||||||
export const NavItem = ({ icon, children, ...rest }: NavItemProps) => {
|
export const NavItem = ({ icon, children, ...rest }: NavItemProps) => {
|
||||||
return (
|
return (
|
||||||
@@ -204,7 +335,7 @@ export const MobileNav = ({ onOpen, ...rest }: MobileProps) => {
|
|||||||
transition="all 0.3s"
|
transition="all 0.3s"
|
||||||
_focus={{ boxShadow: 'none' }}
|
_focus={{ boxShadow: 'none' }}
|
||||||
>
|
>
|
||||||
<HStack>
|
<HStack mr={5}>
|
||||||
<FiUser />
|
<FiUser />
|
||||||
<VStack
|
<VStack
|
||||||
display={{ base: 'none', md: 'flex' }}
|
display={{ base: 'none', md: 'flex' }}
|
||||||
|
@@ -128,3 +128,17 @@ export interface envVarTypes {
|
|||||||
DATABASE_URL: string;
|
DATABASE_URL: string;
|
||||||
ACCESS_TOKEN_EXPIRY_TIME: string;
|
ACCESS_TOKEN_EXPIRY_TIME: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const envSubViews = {
|
||||||
|
INSTANCE_INFO: 'instance-info',
|
||||||
|
ROLES: 'roles',
|
||||||
|
JWT_CONFIG: 'jwt-config',
|
||||||
|
SESSION_STORAGE: 'session-storage',
|
||||||
|
EMAIL_CONFIG: 'email-config',
|
||||||
|
WHITELIST_VARIABLES: 'whitelist-variables',
|
||||||
|
ORGANIZATION_INFO: 'organization-info',
|
||||||
|
ACCESS_TOKEN: 'access-token',
|
||||||
|
UI_CUSTOMIZATION: 'ui-customization',
|
||||||
|
ADMIN_SECRET: 'admin-secret',
|
||||||
|
DB_CRED: 'db-cred',
|
||||||
|
};
|
||||||
|
@@ -2,4 +2,9 @@ import React from 'react';
|
|||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
import App from './App';
|
import App from './App';
|
||||||
|
|
||||||
ReactDOM.render(<App />, document.getElementById('root'));
|
ReactDOM.render(
|
||||||
|
<div>
|
||||||
|
<App />
|
||||||
|
</div>,
|
||||||
|
document.getElementById('root')
|
||||||
|
);
|
||||||
|
@@ -1,20 +1,27 @@
|
|||||||
import { Box, Flex, Image, Text, Spinner } from '@chakra-ui/react';
|
import {
|
||||||
|
Box,
|
||||||
|
Flex,
|
||||||
|
Image,
|
||||||
|
Text,
|
||||||
|
Spinner,
|
||||||
|
useMediaQuery,
|
||||||
|
} from '@chakra-ui/react';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useQuery } from 'urql';
|
import { useQuery } from 'urql';
|
||||||
import { MetaQuery } from '../graphql/queries';
|
import { MetaQuery } from '../graphql/queries';
|
||||||
|
|
||||||
export function AuthLayout({ children }: { children: React.ReactNode }) {
|
export function AuthLayout({ children }: { children: React.ReactNode }) {
|
||||||
const [{ fetching, data }] = useQuery({ query: MetaQuery });
|
const [{ fetching, data }] = useQuery({ query: MetaQuery });
|
||||||
|
const [isNotSmallerScreen] = useMediaQuery('(min-width:600px)');
|
||||||
return (
|
return (
|
||||||
<Flex
|
<Flex
|
||||||
flexWrap="wrap"
|
h="100vh"
|
||||||
h="100%"
|
|
||||||
bg="gray.100"
|
bg="gray.100"
|
||||||
alignItems="center"
|
alignItems="center"
|
||||||
justifyContent="center"
|
justifyContent="center"
|
||||||
flexDirection="column"
|
direction={['column', 'column']}
|
||||||
>
|
>
|
||||||
<Flex alignItems="center">
|
<Flex alignItems="center" maxW="100%">
|
||||||
<Image
|
<Image
|
||||||
src="https://authorizer.dev/images/logo.png"
|
src="https://authorizer.dev/images/logo.png"
|
||||||
alt="logo"
|
alt="logo"
|
||||||
@@ -29,7 +36,15 @@ export function AuthLayout({ children }: { children: React.ReactNode }) {
|
|||||||
<Spinner />
|
<Spinner />
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<Box p="6" m="5" rounded="5" bg="white" w="500px" shadow="xl">
|
<Box
|
||||||
|
p="6"
|
||||||
|
m="5"
|
||||||
|
rounded="5"
|
||||||
|
bg="white"
|
||||||
|
w={isNotSmallerScreen ? '500px' : '450px'}
|
||||||
|
shadow="xl"
|
||||||
|
maxW="100%"
|
||||||
|
>
|
||||||
{children}
|
{children}
|
||||||
</Box>
|
</Box>
|
||||||
<Text color="gray.600" fontSize="sm">
|
<Text color="gray.600" fontSize="sm">
|
||||||
|
@@ -1,46 +1,35 @@
|
|||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import {
|
import { useParams } from 'react-router-dom';
|
||||||
Box,
|
import { Box, Flex, Stack, Button, useToast } from '@chakra-ui/react';
|
||||||
Divider,
|
|
||||||
Flex,
|
|
||||||
Stack,
|
|
||||||
Center,
|
|
||||||
Text,
|
|
||||||
Button,
|
|
||||||
Input,
|
|
||||||
InputGroup,
|
|
||||||
InputRightElement,
|
|
||||||
useToast,
|
|
||||||
} from '@chakra-ui/react';
|
|
||||||
import { useClient } from 'urql';
|
import { useClient } from 'urql';
|
||||||
import {
|
import { FaSave } from 'react-icons/fa';
|
||||||
FaGoogle,
|
|
||||||
FaGithub,
|
|
||||||
FaFacebookF,
|
|
||||||
FaSave,
|
|
||||||
FaRegEyeSlash,
|
|
||||||
FaRegEye,
|
|
||||||
} from 'react-icons/fa';
|
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import InputField from '../components/InputField';
|
|
||||||
import { EnvVariablesQuery } from '../graphql/queries';
|
import { EnvVariablesQuery } from '../graphql/queries';
|
||||||
import {
|
import {
|
||||||
ArrayInputType,
|
|
||||||
SelectInputType,
|
SelectInputType,
|
||||||
HiddenInputType,
|
HiddenInputType,
|
||||||
TextInputType,
|
TextInputType,
|
||||||
TextAreaInputType,
|
|
||||||
SwitchInputType,
|
|
||||||
HMACEncryptionType,
|
HMACEncryptionType,
|
||||||
RSAEncryptionType,
|
RSAEncryptionType,
|
||||||
ECDSAEncryptionType,
|
ECDSAEncryptionType,
|
||||||
envVarTypes,
|
envVarTypes,
|
||||||
|
envSubViews,
|
||||||
} from '../constants';
|
} from '../constants';
|
||||||
import { UpdateEnvVariables } from '../graphql/mutation';
|
import { UpdateEnvVariables } from '../graphql/mutation';
|
||||||
import { getObjectDiff, capitalizeFirstLetter } from '../utils';
|
import { getObjectDiff, capitalizeFirstLetter } from '../utils';
|
||||||
import GenerateKeysModal from '../components/GenerateKeysModal';
|
import OAuthConfig from '../components/EnvComponents/OAuthConfig';
|
||||||
|
import Roles from '../components/EnvComponents/Roles';
|
||||||
|
import JWTConfigurations from '../components/EnvComponents/JWTConfiguration';
|
||||||
|
import SessionStorage from '../components/EnvComponents/SessionStorage';
|
||||||
|
import EmailConfigurations from '../components/EnvComponents/EmailConfiguration';
|
||||||
|
import DomainWhiteListing from '../components/EnvComponents/DomainWhitelisting';
|
||||||
|
import OrganizationInfo from '../components/EnvComponents/OrganizationInfo';
|
||||||
|
import AccessToken from '../components/EnvComponents/AccessToken';
|
||||||
|
import UICustomization from '../components/EnvComponents/UICustomization';
|
||||||
|
import SecurityAdminSecret from '../components/EnvComponents/SecurityAdminSecret';
|
||||||
|
import DatabaseCredentials from '../components/EnvComponents/DatabaseCredentials';
|
||||||
|
|
||||||
export default function Environment() {
|
const Environment = () => {
|
||||||
const client = useClient();
|
const client = useClient();
|
||||||
const toast = useToast();
|
const toast = useToast();
|
||||||
const [adminSecret, setAdminSecret] = React.useState<
|
const [adminSecret, setAdminSecret] = React.useState<
|
||||||
@@ -100,11 +89,14 @@ export default function Environment() {
|
|||||||
OLD_ADMIN_SECRET: false,
|
OLD_ADMIN_SECRET: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const { sec } = useParams();
|
||||||
|
|
||||||
async function getData() {
|
async function getData() {
|
||||||
const {
|
const {
|
||||||
data: { _env: envData },
|
data: { _env: envData },
|
||||||
} = await client.query(EnvVariablesQuery).toPromise();
|
} = await client.query(EnvVariablesQuery).toPromise();
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
|
|
||||||
setEnvVariables({
|
setEnvVariables({
|
||||||
...envData,
|
...envData,
|
||||||
OLD_ADMIN_SECRET: envData.ADMIN_SECRET,
|
OLD_ADMIN_SECRET: envData.ADMIN_SECRET,
|
||||||
@@ -118,7 +110,7 @@ export default function Environment() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getData();
|
getData();
|
||||||
}, []);
|
}, [sec]);
|
||||||
|
|
||||||
const validateAdminSecretHandler = (event: any) => {
|
const validateAdminSecretHandler = (event: any) => {
|
||||||
if (envVariables.OLD_ADMIN_SECRET === event.target.value) {
|
if (envVariables.OLD_ADMIN_SECRET === event.target.value) {
|
||||||
@@ -200,636 +192,113 @@ export default function Environment() {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
const renderComponent = (tab: any) => {
|
||||||
<Box m="5" py="5" px="10" bg="white" rounded="md">
|
switch (tab) {
|
||||||
<Text fontSize="md" paddingTop="2%" fontWeight="bold">
|
case envSubViews.INSTANCE_INFO:
|
||||||
Your instance information
|
return (
|
||||||
</Text>
|
<OAuthConfig
|
||||||
<Stack spacing={6} padding="2% 0%">
|
envVariables={envVariables}
|
||||||
<Flex>
|
setVariables={setEnvVariables}
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
fieldVisibility={fieldVisibility}
|
||||||
<Text fontSize="sm">Client ID</Text>
|
setFieldVisibility={setFieldVisibility}
|
||||||
</Flex>
|
/>
|
||||||
<Center w="70%">
|
);
|
||||||
<InputField
|
case envSubViews.ROLES:
|
||||||
variables={envVariables}
|
return (
|
||||||
setVariables={() => {}}
|
<Roles variables={envVariables} setVariables={setEnvVariables} />
|
||||||
inputType={TextInputType.CLIENT_ID}
|
);
|
||||||
placeholder="Client ID"
|
case envSubViews.JWT_CONFIG:
|
||||||
readOnly={true}
|
return (
|
||||||
/>
|
<JWTConfigurations
|
||||||
</Center>
|
variables={envVariables}
|
||||||
</Flex>
|
setVariables={setEnvVariables}
|
||||||
<Flex>
|
fieldVisibility={fieldVisibility}
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
setFieldVisibility={setFieldVisibility}
|
||||||
<Text fontSize="sm">Client Secret</Text>
|
SelectInputType={SelectInputType.JWT_TYPE}
|
||||||
</Flex>
|
HMACEncryptionType={HMACEncryptionType}
|
||||||
<Center w="70%">
|
RSAEncryptionType={RSAEncryptionType}
|
||||||
<InputField
|
ECDSAEncryptionType={ECDSAEncryptionType}
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
fieldVisibility={fieldVisibility}
|
|
||||||
setFieldVisibility={setFieldVisibility}
|
|
||||||
inputType={HiddenInputType.CLIENT_SECRET}
|
|
||||||
placeholder="Client Secret"
|
|
||||||
readOnly={true}
|
|
||||||
/>
|
|
||||||
</Center>
|
|
||||||
</Flex>
|
|
||||||
</Stack>
|
|
||||||
<Divider marginTop="2%" marginBottom="2%" />
|
|
||||||
<Text fontSize="md" paddingTop="2%" fontWeight="bold">
|
|
||||||
Social Media Logins
|
|
||||||
</Text>
|
|
||||||
<Stack spacing={6} padding="2% 0%">
|
|
||||||
<Flex>
|
|
||||||
<Center
|
|
||||||
w="50px"
|
|
||||||
marginRight="1.5%"
|
|
||||||
border="1px solid #e2e8f0"
|
|
||||||
borderRadius="5px"
|
|
||||||
>
|
|
||||||
<FaGoogle style={{ color: '#8c8c8c' }} />
|
|
||||||
</Center>
|
|
||||||
<Center w="45%" marginRight="1.5%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
inputType={TextInputType.GOOGLE_CLIENT_ID}
|
|
||||||
placeholder="Google Client ID"
|
|
||||||
/>
|
|
||||||
</Center>
|
|
||||||
<Center w="45%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
fieldVisibility={fieldVisibility}
|
|
||||||
setFieldVisibility={setFieldVisibility}
|
|
||||||
inputType={HiddenInputType.GOOGLE_CLIENT_SECRET}
|
|
||||||
placeholder="Google Secret"
|
|
||||||
/>
|
|
||||||
</Center>
|
|
||||||
</Flex>
|
|
||||||
<Flex>
|
|
||||||
<Center
|
|
||||||
w="50px"
|
|
||||||
marginRight="1.5%"
|
|
||||||
border="1px solid #e2e8f0"
|
|
||||||
borderRadius="5px"
|
|
||||||
>
|
|
||||||
<FaGithub style={{ color: '#8c8c8c' }} />
|
|
||||||
</Center>
|
|
||||||
<Center w="45%" marginRight="1.5%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
inputType={TextInputType.GITHUB_CLIENT_ID}
|
|
||||||
placeholder="Github Client ID"
|
|
||||||
/>
|
|
||||||
</Center>
|
|
||||||
<Center w="45%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
fieldVisibility={fieldVisibility}
|
|
||||||
setFieldVisibility={setFieldVisibility}
|
|
||||||
inputType={HiddenInputType.GITHUB_CLIENT_SECRET}
|
|
||||||
placeholder="Github Secret"
|
|
||||||
/>
|
|
||||||
</Center>
|
|
||||||
</Flex>
|
|
||||||
<Flex>
|
|
||||||
<Center
|
|
||||||
w="50px"
|
|
||||||
marginRight="1.5%"
|
|
||||||
border="1px solid #e2e8f0"
|
|
||||||
borderRadius="5px"
|
|
||||||
>
|
|
||||||
<FaFacebookF style={{ color: '#8c8c8c' }} />
|
|
||||||
</Center>
|
|
||||||
<Center w="45%" marginRight="1.5%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
inputType={TextInputType.FACEBOOK_CLIENT_ID}
|
|
||||||
placeholder="Facebook Client ID"
|
|
||||||
/>
|
|
||||||
</Center>
|
|
||||||
<Center w="45%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
fieldVisibility={fieldVisibility}
|
|
||||||
setFieldVisibility={setFieldVisibility}
|
|
||||||
inputType={HiddenInputType.FACEBOOK_CLIENT_SECRET}
|
|
||||||
placeholder="Facebook Secret"
|
|
||||||
/>
|
|
||||||
</Center>
|
|
||||||
</Flex>
|
|
||||||
</Stack>
|
|
||||||
<Divider marginTop="2%" marginBottom="2%" />
|
|
||||||
<Text fontSize="md" paddingTop="2%" fontWeight="bold">
|
|
||||||
Roles
|
|
||||||
</Text>
|
|
||||||
<Stack spacing={6} padding="2% 0%">
|
|
||||||
<Flex>
|
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
|
||||||
<Text fontSize="sm">Roles:</Text>
|
|
||||||
</Flex>
|
|
||||||
<Center w="70%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
inputType={ArrayInputType.ROLES}
|
|
||||||
/>
|
|
||||||
</Center>
|
|
||||||
</Flex>
|
|
||||||
<Flex>
|
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
|
||||||
<Text fontSize="sm">Default Roles:</Text>
|
|
||||||
</Flex>
|
|
||||||
<Center w="70%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
inputType={ArrayInputType.DEFAULT_ROLES}
|
|
||||||
/>
|
|
||||||
</Center>
|
|
||||||
</Flex>
|
|
||||||
<Flex>
|
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
|
||||||
<Text fontSize="sm">Protected Roles:</Text>
|
|
||||||
</Flex>
|
|
||||||
<Center w="70%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
inputType={ArrayInputType.PROTECTED_ROLES}
|
|
||||||
/>
|
|
||||||
</Center>
|
|
||||||
</Flex>
|
|
||||||
</Stack>
|
|
||||||
<Divider marginTop="2%" marginBottom="2%" />
|
|
||||||
<Flex
|
|
||||||
width="100%"
|
|
||||||
justifyContent="space-between"
|
|
||||||
alignItems="center"
|
|
||||||
paddingTop="2%"
|
|
||||||
>
|
|
||||||
<Text fontSize="md" fontWeight="bold">
|
|
||||||
JWT (JSON Web Tokens) Configurations
|
|
||||||
</Text>
|
|
||||||
<Flex>
|
|
||||||
<GenerateKeysModal
|
|
||||||
jwtType={envVariables.JWT_TYPE}
|
|
||||||
getData={getData}
|
getData={getData}
|
||||||
/>
|
/>
|
||||||
</Flex>
|
);
|
||||||
</Flex>
|
case envSubViews.SESSION_STORAGE:
|
||||||
<Stack spacing={6} padding="2% 0%">
|
return (
|
||||||
<Flex>
|
<SessionStorage
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
variables={envVariables}
|
||||||
<Text fontSize="sm">JWT Type:</Text>
|
setVariables={setEnvVariables}
|
||||||
</Flex>
|
RedisURL={TextInputType.REDIS_URL}
|
||||||
<Flex w="70%">
|
/>
|
||||||
<InputField
|
);
|
||||||
variables={envVariables}
|
case envSubViews.EMAIL_CONFIG:
|
||||||
setVariables={setEnvVariables}
|
return (
|
||||||
inputType={SelectInputType.JWT_TYPE}
|
<EmailConfigurations
|
||||||
value={SelectInputType.JWT_TYPE}
|
variables={envVariables}
|
||||||
options={{
|
setVariables={setEnvVariables}
|
||||||
...HMACEncryptionType,
|
fieldVisibility={fieldVisibility}
|
||||||
...RSAEncryptionType,
|
setFieldVisibility={setFieldVisibility}
|
||||||
...ECDSAEncryptionType,
|
/>
|
||||||
}}
|
);
|
||||||
/>
|
case envSubViews.WHITELIST_VARIABLES:
|
||||||
</Flex>
|
return (
|
||||||
</Flex>
|
<DomainWhiteListing
|
||||||
{Object.values(HMACEncryptionType).includes(envVariables.JWT_TYPE) ? (
|
variables={envVariables}
|
||||||
<Flex>
|
setVariables={setEnvVariables}
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
/>
|
||||||
<Text fontSize="sm">JWT Secret</Text>
|
);
|
||||||
</Flex>
|
case envSubViews.ORGANIZATION_INFO:
|
||||||
<Center w="70%">
|
return (
|
||||||
<InputField
|
<OrganizationInfo
|
||||||
variables={envVariables}
|
variables={envVariables}
|
||||||
setVariables={setEnvVariables}
|
setVariables={setEnvVariables}
|
||||||
fieldVisibility={fieldVisibility}
|
/>
|
||||||
setFieldVisibility={setFieldVisibility}
|
);
|
||||||
inputType={HiddenInputType.JWT_SECRET}
|
case envSubViews.ACCESS_TOKEN:
|
||||||
/>
|
return (
|
||||||
</Center>
|
<AccessToken
|
||||||
</Flex>
|
variables={envVariables}
|
||||||
) : (
|
setVariables={setEnvVariables}
|
||||||
<>
|
/>
|
||||||
<Flex>
|
);
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
case envSubViews.UI_CUSTOMIZATION:
|
||||||
<Text fontSize="sm">Public Key</Text>
|
return (
|
||||||
</Flex>
|
<UICustomization
|
||||||
<Center w="70%">
|
variables={envVariables}
|
||||||
<InputField
|
setVariables={setEnvVariables}
|
||||||
variables={envVariables}
|
/>
|
||||||
setVariables={setEnvVariables}
|
);
|
||||||
inputType={TextAreaInputType.JWT_PUBLIC_KEY}
|
case envSubViews.ADMIN_SECRET:
|
||||||
placeholder="Add public key here"
|
return (
|
||||||
minH="25vh"
|
<SecurityAdminSecret
|
||||||
/>
|
variables={envVariables}
|
||||||
</Center>
|
setVariables={setEnvVariables}
|
||||||
</Flex>
|
fieldVisibility={fieldVisibility}
|
||||||
<Flex>
|
setFieldVisibility={setFieldVisibility}
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
validateAdminSecretHandler={validateAdminSecretHandler}
|
||||||
<Text fontSize="sm">Private Key</Text>
|
adminSecret={adminSecret}
|
||||||
</Flex>
|
/>
|
||||||
<Center w="70%">
|
);
|
||||||
<InputField
|
case envSubViews.DB_CRED:
|
||||||
variables={envVariables}
|
return (
|
||||||
setVariables={setEnvVariables}
|
<DatabaseCredentials
|
||||||
inputType={TextAreaInputType.JWT_PRIVATE_KEY}
|
variables={envVariables}
|
||||||
placeholder="Add private key here"
|
setVariables={setEnvVariables}
|
||||||
minH="25vh"
|
/>
|
||||||
/>
|
);
|
||||||
</Center>
|
default:
|
||||||
</Flex>
|
return (
|
||||||
</>
|
<OAuthConfig
|
||||||
)}
|
envVariables={envVariables}
|
||||||
<Flex>
|
setVariables={setEnvVariables}
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
fieldVisibility={fieldVisibility}
|
||||||
<Text fontSize="sm">JWT Role Claim:</Text>
|
setFieldVisibility={setFieldVisibility}
|
||||||
</Flex>
|
/>
|
||||||
<Center w="70%">
|
);
|
||||||
<InputField
|
}
|
||||||
variables={envVariables}
|
};
|
||||||
setVariables={setEnvVariables}
|
return (
|
||||||
inputType={TextInputType.JWT_ROLE_CLAIM}
|
<Box m="5" py="5" px="10" bg="white" rounded="md">
|
||||||
/>
|
{renderComponent(sec)}
|
||||||
</Center>
|
<Stack spacing={6} padding="1% 0" mt={4}>
|
||||||
</Flex>
|
|
||||||
</Stack>
|
|
||||||
<Divider marginTop="2%" marginBottom="2%" />
|
|
||||||
<Text fontSize="md" paddingTop="2%" fontWeight="bold">
|
|
||||||
Session Storage
|
|
||||||
</Text>
|
|
||||||
<Stack spacing={6} padding="2% 0%">
|
|
||||||
<Flex>
|
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
|
||||||
<Text fontSize="sm">Redis URL:</Text>
|
|
||||||
</Flex>
|
|
||||||
<Center w="70%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
inputType={TextInputType.REDIS_URL}
|
|
||||||
/>
|
|
||||||
</Center>
|
|
||||||
</Flex>
|
|
||||||
</Stack>
|
|
||||||
<Divider marginTop="2%" marginBottom="2%" />
|
|
||||||
<Text fontSize="md" paddingTop="2%" fontWeight="bold">
|
|
||||||
Email Configurations
|
|
||||||
</Text>
|
|
||||||
<Stack spacing={6} padding="2% 0%">
|
|
||||||
<Flex>
|
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
|
||||||
<Text fontSize="sm">SMTP Host:</Text>
|
|
||||||
</Flex>
|
|
||||||
<Center w="70%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
inputType={TextInputType.SMTP_HOST}
|
|
||||||
/>
|
|
||||||
</Center>
|
|
||||||
</Flex>
|
|
||||||
<Flex>
|
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
|
||||||
<Text fontSize="sm">SMTP Port:</Text>
|
|
||||||
</Flex>
|
|
||||||
<Center w="70%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
inputType={TextInputType.SMTP_PORT}
|
|
||||||
/>
|
|
||||||
</Center>
|
|
||||||
</Flex>
|
|
||||||
<Flex>
|
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
|
||||||
<Text fontSize="sm">SMTP Username:</Text>
|
|
||||||
</Flex>
|
|
||||||
<Center w="70%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
inputType={TextInputType.SMTP_USERNAME}
|
|
||||||
/>
|
|
||||||
</Center>
|
|
||||||
</Flex>
|
|
||||||
<Flex>
|
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
|
||||||
<Text fontSize="sm">SMTP Password:</Text>
|
|
||||||
</Flex>
|
|
||||||
<Center w="70%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
fieldVisibility={fieldVisibility}
|
|
||||||
setFieldVisibility={setFieldVisibility}
|
|
||||||
inputType={HiddenInputType.SMTP_PASSWORD}
|
|
||||||
/>
|
|
||||||
</Center>
|
|
||||||
</Flex>
|
|
||||||
<Flex>
|
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
|
||||||
<Text fontSize="sm">From Email:</Text>
|
|
||||||
</Flex>
|
|
||||||
<Center w="70%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
inputType={TextInputType.SENDER_EMAIL}
|
|
||||||
/>
|
|
||||||
</Center>
|
|
||||||
</Flex>
|
|
||||||
</Stack>
|
|
||||||
<Divider marginTop="2%" marginBottom="2%" />
|
|
||||||
<Text fontSize="md" paddingTop="2%" fontWeight="bold">
|
|
||||||
White Listing
|
|
||||||
</Text>
|
|
||||||
<Stack spacing={6} padding="2% 0%">
|
|
||||||
<Flex>
|
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
|
||||||
<Text fontSize="sm">Allowed Origins:</Text>
|
|
||||||
</Flex>
|
|
||||||
<Center w="70%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
inputType={ArrayInputType.ALLOWED_ORIGINS}
|
|
||||||
/>
|
|
||||||
</Center>
|
|
||||||
</Flex>
|
|
||||||
</Stack>
|
|
||||||
<Divider marginTop="2%" marginBottom="2%" />
|
|
||||||
<Text fontSize="md" paddingTop="2%" fontWeight="bold">
|
|
||||||
Organization Information
|
|
||||||
</Text>
|
|
||||||
<Stack spacing={6} padding="2% 0%">
|
|
||||||
<Flex>
|
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
|
||||||
<Text fontSize="sm">Organization Name:</Text>
|
|
||||||
</Flex>
|
|
||||||
<Center w="70%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
inputType={TextInputType.ORGANIZATION_NAME}
|
|
||||||
/>
|
|
||||||
</Center>
|
|
||||||
</Flex>
|
|
||||||
<Flex>
|
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
|
||||||
<Text fontSize="sm">Organization Logo:</Text>
|
|
||||||
</Flex>
|
|
||||||
<Center w="70%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
inputType={TextInputType.ORGANIZATION_LOGO}
|
|
||||||
/>
|
|
||||||
</Center>
|
|
||||||
</Flex>
|
|
||||||
</Stack>
|
|
||||||
<Divider marginTop="2%" marginBottom="2%" />
|
|
||||||
<Text fontSize="md" paddingTop="2%" fontWeight="bold">
|
|
||||||
Access Token
|
|
||||||
</Text>
|
|
||||||
<Stack spacing={6} padding="2% 0%">
|
|
||||||
<Flex>
|
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
|
||||||
<Text fontSize="sm">Access Token Expiry Time:</Text>
|
|
||||||
</Flex>
|
|
||||||
<Flex w="70%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
inputType={TextInputType.ACCESS_TOKEN_EXPIRY_TIME}
|
|
||||||
placeholder="0h15m0s"
|
|
||||||
/>
|
|
||||||
</Flex>
|
|
||||||
</Flex>
|
|
||||||
<Flex>
|
|
||||||
<Flex w="30%" justifyContent="start" direction="column">
|
|
||||||
<Text fontSize="sm">Custom Scripts:</Text>
|
|
||||||
<Text fontSize="sm">Used to add custom fields in ID token</Text>
|
|
||||||
</Flex>
|
|
||||||
<Flex w="70%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
inputType={TextAreaInputType.CUSTOM_ACCESS_TOKEN_SCRIPT}
|
|
||||||
placeholder="Add script here"
|
|
||||||
minH="25vh"
|
|
||||||
/>
|
|
||||||
</Flex>
|
|
||||||
</Flex>
|
|
||||||
</Stack>
|
|
||||||
<Divider marginTop="2%" marginBottom="2%" />
|
|
||||||
<Text fontSize="md" paddingTop="2%" fontWeight="bold">
|
|
||||||
Disable Features
|
|
||||||
</Text>
|
|
||||||
<Stack spacing={6} padding="2% 0%">
|
|
||||||
<Flex>
|
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
|
||||||
<Text fontSize="sm">Disable Login Page:</Text>
|
|
||||||
</Flex>
|
|
||||||
<Flex justifyContent="start" w="70%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
inputType={SwitchInputType.DISABLE_LOGIN_PAGE}
|
|
||||||
/>
|
|
||||||
</Flex>
|
|
||||||
</Flex>
|
|
||||||
<Flex>
|
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
|
||||||
<Text fontSize="sm">Disable Email Verification:</Text>
|
|
||||||
</Flex>
|
|
||||||
<Flex justifyContent="start" w="70%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
inputType={SwitchInputType.DISABLE_EMAIL_VERIFICATION}
|
|
||||||
/>
|
|
||||||
</Flex>
|
|
||||||
</Flex>
|
|
||||||
<Flex>
|
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
|
||||||
<Text fontSize="sm">Disable Magic Login Link:</Text>
|
|
||||||
</Flex>
|
|
||||||
<Flex justifyContent="start" w="70%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
inputType={SwitchInputType.DISABLE_MAGIC_LINK_LOGIN}
|
|
||||||
/>
|
|
||||||
</Flex>
|
|
||||||
</Flex>
|
|
||||||
<Flex>
|
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
|
||||||
<Text fontSize="sm">Disable Basic Authentication:</Text>
|
|
||||||
</Flex>
|
|
||||||
<Flex justifyContent="start" w="70%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
inputType={SwitchInputType.DISABLE_BASIC_AUTHENTICATION}
|
|
||||||
/>
|
|
||||||
</Flex>
|
|
||||||
</Flex>
|
|
||||||
<Flex>
|
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
|
||||||
<Text fontSize="sm">Disable Sign Up:</Text>
|
|
||||||
</Flex>
|
|
||||||
<Flex justifyContent="start" w="70%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
inputType={SwitchInputType.DISABLE_SIGN_UP}
|
|
||||||
/>
|
|
||||||
</Flex>
|
|
||||||
</Flex>
|
|
||||||
</Stack>
|
|
||||||
<Divider marginTop="2%" marginBottom="2%" />
|
|
||||||
<Text fontSize="md" paddingTop="2%" fontWeight="bold">
|
|
||||||
Danger
|
|
||||||
</Text>
|
|
||||||
<Stack
|
|
||||||
spacing={6}
|
|
||||||
padding="0 5%"
|
|
||||||
marginTop="3%"
|
|
||||||
border="1px solid #ff7875"
|
|
||||||
borderRadius="5px"
|
|
||||||
>
|
|
||||||
<Stack spacing={6} padding="3% 0">
|
|
||||||
<Text fontStyle="italic" fontSize="sm" color="gray.600">
|
|
||||||
Note: Database related environment variables cannot be updated from
|
|
||||||
dashboard :(
|
|
||||||
</Text>
|
|
||||||
<Flex>
|
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
|
||||||
<Text fontSize="sm">DataBase Name:</Text>
|
|
||||||
</Flex>
|
|
||||||
<Center w="70%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
inputType={TextInputType.DATABASE_NAME}
|
|
||||||
isDisabled={true}
|
|
||||||
/>
|
|
||||||
</Center>
|
|
||||||
</Flex>
|
|
||||||
<Flex>
|
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
|
||||||
<Text fontSize="sm">DataBase Type:</Text>
|
|
||||||
</Flex>
|
|
||||||
<Center w="70%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
inputType={TextInputType.DATABASE_TYPE}
|
|
||||||
isDisabled={true}
|
|
||||||
/>
|
|
||||||
</Center>
|
|
||||||
</Flex>
|
|
||||||
<Flex>
|
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
|
||||||
<Text fontSize="sm">DataBase URL:</Text>
|
|
||||||
</Flex>
|
|
||||||
<Center w="70%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
inputType={TextInputType.DATABASE_URL}
|
|
||||||
isDisabled={true}
|
|
||||||
/>
|
|
||||||
</Center>
|
|
||||||
</Flex>
|
|
||||||
</Stack>
|
|
||||||
<Flex marginTop="3%">
|
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
|
||||||
<Text fontSize="sm">Old Admin Secret:</Text>
|
|
||||||
</Flex>
|
|
||||||
<Center w="70%">
|
|
||||||
<InputGroup size="sm">
|
|
||||||
<Input
|
|
||||||
size="sm"
|
|
||||||
placeholder="Enter Old Admin Secret"
|
|
||||||
value={adminSecret.value as string}
|
|
||||||
onChange={(event: any) => validateAdminSecretHandler(event)}
|
|
||||||
type={
|
|
||||||
!fieldVisibility[HiddenInputType.OLD_ADMIN_SECRET]
|
|
||||||
? 'password'
|
|
||||||
: 'text'
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<InputRightElement
|
|
||||||
right="5px"
|
|
||||||
children={
|
|
||||||
<Flex>
|
|
||||||
{fieldVisibility[HiddenInputType.OLD_ADMIN_SECRET] ? (
|
|
||||||
<Center
|
|
||||||
w="25px"
|
|
||||||
margin="0 1.5%"
|
|
||||||
cursor="pointer"
|
|
||||||
onClick={() =>
|
|
||||||
setFieldVisibility({
|
|
||||||
...fieldVisibility,
|
|
||||||
[HiddenInputType.OLD_ADMIN_SECRET]: false,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<FaRegEyeSlash color="#bfbfbf" />
|
|
||||||
</Center>
|
|
||||||
) : (
|
|
||||||
<Center
|
|
||||||
w="25px"
|
|
||||||
margin="0 1.5%"
|
|
||||||
cursor="pointer"
|
|
||||||
onClick={() =>
|
|
||||||
setFieldVisibility({
|
|
||||||
...fieldVisibility,
|
|
||||||
[HiddenInputType.OLD_ADMIN_SECRET]: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<FaRegEye color="#bfbfbf" />
|
|
||||||
</Center>
|
|
||||||
)}
|
|
||||||
</Flex>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</InputGroup>
|
|
||||||
</Center>
|
|
||||||
</Flex>
|
|
||||||
<Flex paddingBottom="3%">
|
|
||||||
<Flex w="30%" justifyContent="start" alignItems="center">
|
|
||||||
<Text fontSize="sm">New Admin Secret:</Text>
|
|
||||||
</Flex>
|
|
||||||
<Center w="70%">
|
|
||||||
<InputField
|
|
||||||
variables={envVariables}
|
|
||||||
setVariables={setEnvVariables}
|
|
||||||
inputType={HiddenInputType.ADMIN_SECRET}
|
|
||||||
fieldVisibility={fieldVisibility}
|
|
||||||
setFieldVisibility={setFieldVisibility}
|
|
||||||
isDisabled={adminSecret.disableInputField}
|
|
||||||
placeholder="Enter New Admin Secret"
|
|
||||||
/>
|
|
||||||
</Center>
|
|
||||||
</Flex>
|
|
||||||
</Stack>
|
|
||||||
<Divider marginTop="5%" marginBottom="2%" />
|
|
||||||
<Stack spacing={6} padding="1% 0">
|
|
||||||
<Flex justifyContent="end" alignItems="center">
|
<Flex justifyContent="end" alignItems="center">
|
||||||
<Button
|
<Button
|
||||||
leftIcon={<FaSave />}
|
leftIcon={<FaSave />}
|
||||||
@@ -844,4 +313,6 @@ export default function Environment() {
|
|||||||
</Stack>
|
</Stack>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
export default Environment;
|
||||||
|
@@ -14,6 +14,7 @@ export const AppRoutes = () => {
|
|||||||
|
|
||||||
if (isLoggedIn) {
|
if (isLoggedIn) {
|
||||||
return (
|
return (
|
||||||
|
<div>
|
||||||
<Suspense fallback={<></>}>
|
<Suspense fallback={<></>}>
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route
|
<Route
|
||||||
@@ -23,13 +24,16 @@ export const AppRoutes = () => {
|
|||||||
</DashboardLayout>
|
</DashboardLayout>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Route path="/" element={<Environment />} />
|
<Route path="/" element={<Outlet />}>
|
||||||
<Route path="users" element={<Users />} />
|
<Route index element={<Environment />} />
|
||||||
<Route path="environment" element={<Environment />} />
|
<Route path="/:sec" element={<Environment />} />
|
||||||
<Route path="*" element={<Home />} />
|
</Route>
|
||||||
|
<Route path="users" element={<Users />} />
|
||||||
|
<Route path="*" element={<Home />} />
|
||||||
</Route>
|
</Route>
|
||||||
</Routes>
|
</Routes>
|
||||||
</Suspense>
|
</Suspense>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
|
@@ -17,4 +17,6 @@ const (
|
|||||||
DbTypeYugabyte = "yugabyte"
|
DbTypeYugabyte = "yugabyte"
|
||||||
// DbTypeMariaDB is the mariadb database type
|
// DbTypeMariaDB is the mariadb database type
|
||||||
DbTypeMariaDB = "mariadb"
|
DbTypeMariaDB = "mariadb"
|
||||||
|
// DbTypeCassandra is the cassandra database type
|
||||||
|
DbTypeCassandraDB = "cassandradb"
|
||||||
)
|
)
|
||||||
|
@@ -30,6 +30,20 @@ const (
|
|||||||
EnvKeyDatabaseURL = "DATABASE_URL"
|
EnvKeyDatabaseURL = "DATABASE_URL"
|
||||||
// EnvKeyDatabaseName key for env variable DATABASE_NAME
|
// EnvKeyDatabaseName key for env variable DATABASE_NAME
|
||||||
EnvKeyDatabaseName = "DATABASE_NAME"
|
EnvKeyDatabaseName = "DATABASE_NAME"
|
||||||
|
// EnvKeyDatabaseUsername key for env variable DATABASE_USERNAME
|
||||||
|
EnvKeyDatabaseUsername = "DATABASE_USERNAME"
|
||||||
|
// EnvKeyDatabasePassword key for env variable DATABASE_PASSWORD
|
||||||
|
EnvKeyDatabasePassword = "DATABASE_PASSWORD"
|
||||||
|
// EnvKeyDatabasePort key for env variable DATABASE_PORT
|
||||||
|
EnvKeyDatabasePort = "DATABASE_PORT"
|
||||||
|
// EnvKeyDatabaseHost key for env variable DATABASE_HOST
|
||||||
|
EnvKeyDatabaseHost = "DATABASE_HOST"
|
||||||
|
// EnvKeyDatabaseCert key for env variable DATABASE_CERT
|
||||||
|
EnvKeyDatabaseCert = "DATABASE_CERT"
|
||||||
|
// EnvKeyDatabaseCertKey key for env variable DATABASE_KEY
|
||||||
|
EnvKeyDatabaseCertKey = "DATABASE_CERT_KEY"
|
||||||
|
// EnvKeyDatabaseCACert key for env variable DATABASE_CA_CERT
|
||||||
|
EnvKeyDatabaseCACert = "DATABASE_CA_CERT"
|
||||||
// EnvKeySmtpHost key for env variable SMTP_HOST
|
// EnvKeySmtpHost key for env variable SMTP_HOST
|
||||||
EnvKeySmtpHost = "SMTP_HOST"
|
EnvKeySmtpHost = "SMTP_HOST"
|
||||||
// EnvKeySmtpPort key for env variable SMTP_PORT
|
// EnvKeySmtpPort key for env variable SMTP_PORT
|
||||||
|
@@ -1,9 +1,12 @@
|
|||||||
package db
|
package db
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/db/providers"
|
"github.com/authorizerdev/authorizer/server/db/providers"
|
||||||
"github.com/authorizerdev/authorizer/server/db/providers/arangodb"
|
"github.com/authorizerdev/authorizer/server/db/providers/arangodb"
|
||||||
|
"github.com/authorizerdev/authorizer/server/db/providers/cassandradb"
|
||||||
"github.com/authorizerdev/authorizer/server/db/providers/mongodb"
|
"github.com/authorizerdev/authorizer/server/db/providers/mongodb"
|
||||||
"github.com/authorizerdev/authorizer/server/db/providers/sql"
|
"github.com/authorizerdev/authorizer/server/db/providers/sql"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
"github.com/authorizerdev/authorizer/server/envstore"
|
||||||
@@ -15,27 +18,43 @@ var Provider providers.Provider
|
|||||||
func InitDB() error {
|
func InitDB() error {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
isSQL := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType) != constants.DbTypeArangodb && envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType) != constants.DbTypeMongodb
|
isSQL := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType) != constants.DbTypeArangodb && envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType) != constants.DbTypeMongodb && envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType) != constants.DbTypeCassandraDB
|
||||||
isArangoDB := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType) == constants.DbTypeArangodb
|
isArangoDB := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType) == constants.DbTypeArangodb
|
||||||
isMongoDB := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType) == constants.DbTypeMongodb
|
isMongoDB := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType) == constants.DbTypeMongodb
|
||||||
|
isCassandra := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType) == constants.DbTypeCassandraDB
|
||||||
|
|
||||||
if isSQL {
|
if isSQL {
|
||||||
|
log.Info("Initializing SQL Driver for: ", envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType))
|
||||||
Provider, err = sql.NewProvider()
|
Provider, err = sql.NewProvider()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Fatal("Failed to initialize SQL driver: ", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if isArangoDB {
|
if isArangoDB {
|
||||||
|
log.Info("Initializing ArangoDB Driver")
|
||||||
Provider, err = arangodb.NewProvider()
|
Provider, err = arangodb.NewProvider()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Fatal("Failed to initialize ArangoDB driver: ", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if isMongoDB {
|
if isMongoDB {
|
||||||
|
log.Info("Initializing MongoDB Driver")
|
||||||
Provider, err = mongodb.NewProvider()
|
Provider, err = mongodb.NewProvider()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Fatal("Failed to initialize MongoDB driver: ", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if isCassandra {
|
||||||
|
log.Info("Initializing CassandraDB Driver")
|
||||||
|
Provider, err = cassandradb.NewProvider()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("Failed to initialize CassandraDB driver: ", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,11 +1,13 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
|
// Note: any change here should be reflected in providers/casandra/provider.go as it does not have model support in collection creation
|
||||||
|
|
||||||
// Env model for db
|
// Env model for db
|
||||||
type Env struct {
|
type Env struct {
|
||||||
Key string `json:"_key,omitempty" bson:"_key"` // for arangodb
|
Key string `json:"_key,omitempty" bson:"_key,omitempty" cql:"_key,omitempty"` // for arangodb
|
||||||
ID string `gorm:"primaryKey;type:char(36)" json:"_id" bson:"_id"`
|
ID string `gorm:"primaryKey;type:char(36)" json:"_id" bson:"_id" cql:"id"`
|
||||||
EnvData string `gorm:"type:text" json:"env" bson:"env"`
|
EnvData string `gorm:"type:text" json:"env" bson:"env" cql:"env"`
|
||||||
Hash string `gorm:"type:text" json:"hash" bson:"hash"`
|
Hash string `gorm:"type:text" json:"hash" bson:"hash" cql:"hash"`
|
||||||
UpdatedAt int64 `json:"updated_at" bson:"updated_at"`
|
UpdatedAt int64 `json:"updated_at" bson:"updated_at" cql:"updated_at"`
|
||||||
CreatedAt int64 `json:"created_at" bson:"created_at"`
|
CreatedAt int64 `json:"created_at" bson:"created_at" cql:"created_at"`
|
||||||
}
|
}
|
||||||
|
@@ -1,13 +1,15 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
|
// Note: any change here should be reflected in providers/casandra/provider.go as it does not have model support in collection creation
|
||||||
|
|
||||||
// Session model for db
|
// Session model for db
|
||||||
type Session struct {
|
type Session struct {
|
||||||
Key string `json:"_key,omitempty" bson:"_key,omitempty"` // for arangodb
|
Key string `json:"_key,omitempty" bson:"_key,omitempty" cql:"_key,omitempty"` // for arangodb
|
||||||
ID string `gorm:"primaryKey;type:char(36)" json:"_id" bson:"_id"`
|
ID string `gorm:"primaryKey;type:char(36)" json:"_id" bson:"_id" cql:"id"`
|
||||||
UserID string `gorm:"type:char(36),index:" json:"user_id" bson:"user_id"`
|
UserID string `gorm:"type:char(36),index:" json:"user_id" bson:"user_id" cql:"user_id"`
|
||||||
User User `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"-" bson:"-"`
|
User User `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"-" bson:"-" cql:"-"`
|
||||||
UserAgent string `json:"user_agent" bson:"user_agent"`
|
UserAgent string `json:"user_agent" bson:"user_agent" cql:"user_agent"`
|
||||||
IP string `json:"ip" bson:"ip"`
|
IP string `json:"ip" bson:"ip" cql:"ip"`
|
||||||
CreatedAt int64 `json:"created_at" bson:"created_at"`
|
CreatedAt int64 `json:"created_at" bson:"created_at" cql:"created_at"`
|
||||||
UpdatedAt int64 `json:"updated_at" bson:"updated_at"`
|
UpdatedAt int64 `json:"updated_at" bson:"updated_at" cql:"updated_at"`
|
||||||
}
|
}
|
||||||
|
@@ -6,28 +6,30 @@ import (
|
|||||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Note: any change here should be reflected in providers/casandra/provider.go as it does not have model support in collection creation
|
||||||
|
|
||||||
// User model for db
|
// User model for db
|
||||||
type User struct {
|
type User struct {
|
||||||
Key string `json:"_key,omitempty" bson:"_key"` // for arangodb
|
Key string `json:"_key,omitempty" bson:"_key,omitempty" cql:"_key,omitempty"` // for arangodb
|
||||||
ID string `gorm:"primaryKey;type:char(36)" json:"_id" bson:"_id"`
|
ID string `gorm:"primaryKey;type:char(36)" json:"_id" bson:"_id" cql:"id"`
|
||||||
|
|
||||||
Email string `gorm:"unique" json:"email" bson:"email"`
|
Email string `gorm:"unique" json:"email" bson:"email" cql:"email"`
|
||||||
EmailVerifiedAt *int64 `json:"email_verified_at" bson:"email_verified_at"`
|
EmailVerifiedAt *int64 `json:"email_verified_at" bson:"email_verified_at" cql:"email_verified_at"`
|
||||||
Password *string `gorm:"type:text" json:"password" bson:"password"`
|
Password *string `gorm:"type:text" json:"password" bson:"password" cql:"password"`
|
||||||
SignupMethods string `json:"signup_methods" bson:"signup_methods"`
|
SignupMethods string `json:"signup_methods" bson:"signup_methods" cql:"signup_methods"`
|
||||||
GivenName *string `json:"given_name" bson:"given_name"`
|
GivenName *string `json:"given_name" bson:"given_name" cql:"given_name"`
|
||||||
FamilyName *string `json:"family_name" bson:"family_name"`
|
FamilyName *string `json:"family_name" bson:"family_name" cql:"family_name"`
|
||||||
MiddleName *string `json:"middle_name" bson:"middle_name"`
|
MiddleName *string `json:"middle_name" bson:"middle_name" cql:"middle_name"`
|
||||||
Nickname *string `json:"nickname" bson:"nickname"`
|
Nickname *string `json:"nickname" bson:"nickname" cql:"nickname"`
|
||||||
Gender *string `json:"gender" bson:"gender"`
|
Gender *string `json:"gender" bson:"gender" cql:"gender"`
|
||||||
Birthdate *string `json:"birthdate" bson:"birthdate"`
|
Birthdate *string `json:"birthdate" bson:"birthdate" cql:"birthdate"`
|
||||||
PhoneNumber *string `gorm:"unique" json:"phone_number" bson:"phone_number"`
|
PhoneNumber *string `gorm:"unique" json:"phone_number" bson:"phone_number" cql:"phone_number"`
|
||||||
PhoneNumberVerifiedAt *int64 `json:"phone_number_verified_at" bson:"phone_number_verified_at"`
|
PhoneNumberVerifiedAt *int64 `json:"phone_number_verified_at" bson:"phone_number_verified_at" cql:"phone_number_verified_at"`
|
||||||
Picture *string `gorm:"type:text" json:"picture" bson:"picture"`
|
Picture *string `gorm:"type:text" json:"picture" bson:"picture" cql:"picture"`
|
||||||
Roles string `json:"roles" bson:"roles"`
|
Roles string `json:"roles" bson:"roles" cql:"roles"`
|
||||||
UpdatedAt int64 `json:"updated_at" bson:"updated_at"`
|
RevokedTimestamp *int64 `json:"revoked_timestamp" bson:"revoked_timestamp" cql:"revoked_timestamp"`
|
||||||
CreatedAt int64 `json:"created_at" bson:"created_at"`
|
UpdatedAt int64 `json:"updated_at" bson:"updated_at" cql:"updated_at"`
|
||||||
RevokedTimestamp *int64 `json:"revoked_timestamp" bson:"revoked_timestamp"`
|
CreatedAt int64 `json:"created_at" bson:"created_at" cql:"created_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (user *User) AsAPIUser() *model.User {
|
func (user *User) AsAPIUser() *model.User {
|
||||||
@@ -53,8 +55,8 @@ func (user *User) AsAPIUser() *model.User {
|
|||||||
PhoneNumberVerified: &isPhoneVerified,
|
PhoneNumberVerified: &isPhoneVerified,
|
||||||
Picture: user.Picture,
|
Picture: user.Picture,
|
||||||
Roles: strings.Split(user.Roles, ","),
|
Roles: strings.Split(user.Roles, ","),
|
||||||
|
RevokedTimestamp: revokedTimestamp,
|
||||||
CreatedAt: &createdAt,
|
CreatedAt: &createdAt,
|
||||||
UpdatedAt: &updatedAt,
|
UpdatedAt: &updatedAt,
|
||||||
RevokedTimestamp: revokedTimestamp,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,18 +2,20 @@ package models
|
|||||||
|
|
||||||
import "github.com/authorizerdev/authorizer/server/graph/model"
|
import "github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
|
|
||||||
|
// Note: any change here should be reflected in providers/casandra/provider.go as it does not have model support in collection creation
|
||||||
|
|
||||||
// VerificationRequest model for db
|
// VerificationRequest model for db
|
||||||
type VerificationRequest struct {
|
type VerificationRequest struct {
|
||||||
Key string `json:"_key,omitempty" bson:"_key"` // for arangodb
|
Key string `json:"_key,omitempty" bson:"_key" cql:"_key,omitempty"` // for arangodb
|
||||||
ID string `gorm:"primaryKey;type:char(36)" json:"_id" bson:"_id"`
|
ID string `gorm:"primaryKey;type:char(36)" json:"_id" bson:"_id" cql:"id"`
|
||||||
Token string `gorm:"type:text" json:"token" bson:"token"`
|
Token string `gorm:"type:text" json:"token" bson:"token" cql:"jwt_token"` // token is reserved keyword in cassandra
|
||||||
Identifier string `gorm:"uniqueIndex:idx_email_identifier" json:"identifier" bson:"identifier"`
|
Identifier string `gorm:"uniqueIndex:idx_email_identifier;type:varchar(64)" json:"identifier" bson:"identifier" cql:"identifier"`
|
||||||
ExpiresAt int64 `json:"expires_at" bson:"expires_at"`
|
ExpiresAt int64 `json:"expires_at" bson:"expires_at" cql:"expires_at"`
|
||||||
CreatedAt int64 `json:"created_at" bson:"created_at"`
|
Email string `gorm:"uniqueIndex:idx_email_identifier;type:varchar(256)" json:"email" bson:"email" cql:"email"`
|
||||||
UpdatedAt int64 `json:"updated_at" bson:"updated_at"`
|
Nonce string `gorm:"type:text" json:"nonce" bson:"nonce" cql:"nonce"`
|
||||||
Email string `gorm:"uniqueIndex:idx_email_identifier" json:"email" bson:"email"`
|
RedirectURI string `gorm:"type:text" json:"redirect_uri" bson:"redirect_uri" cql:"redirect_uri"`
|
||||||
Nonce string `gorm:"type:text" json:"nonce" bson:"nonce"`
|
CreatedAt int64 `json:"created_at" bson:"created_at" cql:"created_at"`
|
||||||
RedirectURI string `gorm:"type:text" json:"redirect_uri" bson:"redirect_uri"`
|
UpdatedAt int64 `json:"updated_at" bson:"updated_at" cql:"updated_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *VerificationRequest) AsAPIVerificationRequest() *model.VerificationRequest {
|
func (v *VerificationRequest) AsAPIVerificationRequest() *model.VerificationRequest {
|
||||||
@@ -30,10 +32,10 @@ func (v *VerificationRequest) AsAPIVerificationRequest() *model.VerificationRequ
|
|||||||
Token: &token,
|
Token: &token,
|
||||||
Identifier: &identifier,
|
Identifier: &identifier,
|
||||||
Expires: &expires,
|
Expires: &expires,
|
||||||
CreatedAt: &createdAt,
|
|
||||||
UpdatedAt: &updatedAt,
|
|
||||||
Email: &email,
|
Email: &email,
|
||||||
Nonce: &nonce,
|
Nonce: &nonce,
|
||||||
RedirectURI: &redirectURI,
|
RedirectURI: &redirectURI,
|
||||||
|
CreatedAt: &createdAt,
|
||||||
|
UpdatedAt: &updatedAt,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,7 +2,6 @@ package arangodb
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
arangoDriver "github.com/arangodb/go-driver"
|
arangoDriver "github.com/arangodb/go-driver"
|
||||||
@@ -22,7 +21,6 @@ func (p *provider) AddEnv(env models.Env) (models.Env, error) {
|
|||||||
configCollection, _ := p.db.Collection(nil, models.Collections.Env)
|
configCollection, _ := p.db.Collection(nil, models.Collections.Env)
|
||||||
meta, err := configCollection.CreateDocument(arangoDriver.WithOverwrite(nil), env)
|
meta, err := configCollection.CreateDocument(arangoDriver.WithOverwrite(nil), env)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error adding config:", err)
|
|
||||||
return env, err
|
return env, err
|
||||||
}
|
}
|
||||||
env.Key = meta.Key
|
env.Key = meta.Key
|
||||||
@@ -36,7 +34,6 @@ func (p *provider) UpdateEnv(env models.Env) (models.Env, error) {
|
|||||||
collection, _ := p.db.Collection(nil, models.Collections.Env)
|
collection, _ := p.db.Collection(nil, models.Collections.Env)
|
||||||
meta, err := collection.UpdateDocument(nil, env.Key, env)
|
meta, err := collection.UpdateDocument(nil, env.Key, env)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error updating config:", err)
|
|
||||||
return env, err
|
return env, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -2,7 +2,6 @@ package arangodb
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"log"
|
|
||||||
|
|
||||||
"github.com/arangodb/go-driver"
|
"github.com/arangodb/go-driver"
|
||||||
arangoDriver "github.com/arangodb/go-driver"
|
arangoDriver "github.com/arangodb/go-driver"
|
||||||
@@ -42,7 +41,6 @@ func NewProvider() (*provider, error) {
|
|||||||
arangodb_exists, err := arangoClient.DatabaseExists(nil, envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseName))
|
arangodb_exists, err := arangoClient.DatabaseExists(nil, envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseName))
|
||||||
|
|
||||||
if arangodb_exists {
|
if arangodb_exists {
|
||||||
log.Println(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseName) + " db exists already")
|
|
||||||
arangodb, err = arangoClient.Database(nil, envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseName))
|
arangodb, err = arangoClient.Database(nil, envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseName))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -55,12 +53,10 @@ func NewProvider() (*provider, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
userCollectionExists, err := arangodb.CollectionExists(ctx, models.Collections.User)
|
userCollectionExists, err := arangodb.CollectionExists(ctx, models.Collections.User)
|
||||||
if userCollectionExists {
|
if !userCollectionExists {
|
||||||
log.Println(models.Collections.User + " collection exists already")
|
|
||||||
} else {
|
|
||||||
_, err = arangodb.CreateCollection(ctx, models.Collections.User, nil)
|
_, err = arangodb.CreateCollection(ctx, models.Collections.User, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error creating collection("+models.Collections.User+"):", err)
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
userCollection, _ := arangodb.Collection(nil, models.Collections.User)
|
userCollection, _ := arangodb.Collection(nil, models.Collections.User)
|
||||||
@@ -74,12 +70,10 @@ func NewProvider() (*provider, error) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
verificationRequestCollectionExists, err := arangodb.CollectionExists(ctx, models.Collections.VerificationRequest)
|
verificationRequestCollectionExists, err := arangodb.CollectionExists(ctx, models.Collections.VerificationRequest)
|
||||||
if verificationRequestCollectionExists {
|
if !verificationRequestCollectionExists {
|
||||||
log.Println(models.Collections.VerificationRequest + " collection exists already")
|
|
||||||
} else {
|
|
||||||
_, err = arangodb.CreateCollection(ctx, models.Collections.VerificationRequest, nil)
|
_, err = arangodb.CreateCollection(ctx, models.Collections.VerificationRequest, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error creating collection("+models.Collections.VerificationRequest+"):", err)
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,12 +87,10 @@ func NewProvider() (*provider, error) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
sessionCollectionExists, err := arangodb.CollectionExists(ctx, models.Collections.Session)
|
sessionCollectionExists, err := arangodb.CollectionExists(ctx, models.Collections.Session)
|
||||||
if sessionCollectionExists {
|
if !sessionCollectionExists {
|
||||||
log.Println(models.Collections.Session + " collection exists already")
|
|
||||||
} else {
|
|
||||||
_, err = arangodb.CreateCollection(ctx, models.Collections.Session, nil)
|
_, err = arangodb.CreateCollection(ctx, models.Collections.Session, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error creating collection("+models.Collections.Session+"):", err)
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,12 +100,10 @@ func NewProvider() (*provider, error) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
configCollectionExists, err := arangodb.CollectionExists(ctx, models.Collections.Env)
|
configCollectionExists, err := arangodb.CollectionExists(ctx, models.Collections.Env)
|
||||||
if configCollectionExists {
|
if !configCollectionExists {
|
||||||
log.Println(models.Collections.Env + " collection exists already")
|
|
||||||
} else {
|
|
||||||
_, err = arangodb.CreateCollection(ctx, models.Collections.Env, nil)
|
_, err = arangodb.CreateCollection(ctx, models.Collections.Env, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error creating collection("+models.Collections.Env+"):", err)
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@@ -2,7 +2,6 @@ package arangodb
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/db/models"
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
@@ -20,7 +19,6 @@ func (p *provider) AddSession(session models.Session) error {
|
|||||||
sessionCollection, _ := p.db.Collection(nil, models.Collections.Session)
|
sessionCollection, _ := p.db.Collection(nil, models.Collections.Session)
|
||||||
_, err := sessionCollection.CreateDocument(nil, session)
|
_, err := sessionCollection.CreateDocument(nil, session)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(`error saving session`, err)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@@ -3,7 +3,6 @@ package arangodb
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -31,7 +30,6 @@ func (p *provider) AddUser(user models.User) (models.User, error) {
|
|||||||
userCollection, _ := p.db.Collection(nil, models.Collections.User)
|
userCollection, _ := p.db.Collection(nil, models.Collections.User)
|
||||||
meta, err := userCollection.CreateDocument(arangoDriver.WithOverwrite(nil), user)
|
meta, err := userCollection.CreateDocument(arangoDriver.WithOverwrite(nil), user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error adding user:", err)
|
|
||||||
return user, err
|
return user, err
|
||||||
}
|
}
|
||||||
user.Key = meta.Key
|
user.Key = meta.Key
|
||||||
@@ -46,7 +44,6 @@ func (p *provider) UpdateUser(user models.User) (models.User, error) {
|
|||||||
collection, _ := p.db.Collection(nil, models.Collections.User)
|
collection, _ := p.db.Collection(nil, models.Collections.User)
|
||||||
meta, err := collection.UpdateDocument(nil, user.Key, user)
|
meta, err := collection.UpdateDocument(nil, user.Key, user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error updating user:", err)
|
|
||||||
return user, err
|
return user, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,7 +57,6 @@ func (p *provider) DeleteUser(user models.User) error {
|
|||||||
collection, _ := p.db.Collection(nil, models.Collections.User)
|
collection, _ := p.db.Collection(nil, models.Collections.User)
|
||||||
_, err := collection.RemoveDocument(nil, user.Key)
|
_, err := collection.RemoveDocument(nil, user.Key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(`error deleting user:`, err)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -3,7 +3,6 @@ package arangodb
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/arangodb/go-driver"
|
"github.com/arangodb/go-driver"
|
||||||
@@ -23,7 +22,6 @@ func (p *provider) AddVerificationRequest(verificationRequest models.Verificatio
|
|||||||
verificationRequestRequestCollection, _ := p.db.Collection(nil, models.Collections.VerificationRequest)
|
verificationRequestRequestCollection, _ := p.db.Collection(nil, models.Collections.VerificationRequest)
|
||||||
meta, err := verificationRequestRequestCollection.CreateDocument(nil, verificationRequest)
|
meta, err := verificationRequestRequestCollection.CreateDocument(nil, verificationRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error saving verificationRequest record:", err)
|
|
||||||
return verificationRequest, err
|
return verificationRequest, err
|
||||||
}
|
}
|
||||||
verificationRequest.Key = meta.Key
|
verificationRequest.Key = meta.Key
|
||||||
@@ -136,7 +134,6 @@ func (p *provider) DeleteVerificationRequest(verificationRequest models.Verifica
|
|||||||
collection, _ := p.db.Collection(nil, models.Collections.VerificationRequest)
|
collection, _ := p.db.Collection(nil, models.Collections.VerificationRequest)
|
||||||
_, err := collection.RemoveDocument(nil, verificationRequest.Key)
|
_, err := collection.RemoveDocument(nil, verificationRequest.Key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(`error deleting verification request:`, err)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
52
server/db/providers/cassandradb/env.go
Normal file
52
server/db/providers/cassandradb/env.go
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
package cassandradb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
|
"github.com/gocql/gocql"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AddEnv to save environment information in database
|
||||||
|
func (p *provider) AddEnv(env models.Env) (models.Env, error) {
|
||||||
|
if env.ID == "" {
|
||||||
|
env.ID = uuid.New().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
env.CreatedAt = time.Now().Unix()
|
||||||
|
env.UpdatedAt = time.Now().Unix()
|
||||||
|
insertEnvQuery := fmt.Sprintf("INSERT INTO %s (id, env, hash, created_at, updated_at) VALUES ('%s', '%s', '%s', %d, %d)", KeySpace+"."+models.Collections.Env, env.ID, env.EnvData, env.Hash, env.CreatedAt, env.UpdatedAt)
|
||||||
|
err := p.db.Query(insertEnvQuery).Exec()
|
||||||
|
if err != nil {
|
||||||
|
return env, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return env, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateEnv to update environment information in database
|
||||||
|
func (p *provider) UpdateEnv(env models.Env) (models.Env, error) {
|
||||||
|
env.UpdatedAt = time.Now().Unix()
|
||||||
|
|
||||||
|
updateEnvQuery := fmt.Sprintf("UPDATE %s SET env = '%s', updated_at = %d WHERE id = '%s'", KeySpace+"."+models.Collections.Env, env.EnvData, env.UpdatedAt, env.ID)
|
||||||
|
err := p.db.Query(updateEnvQuery).Exec()
|
||||||
|
if err != nil {
|
||||||
|
return env, err
|
||||||
|
}
|
||||||
|
return env, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetEnv to get environment information from database
|
||||||
|
func (p *provider) GetEnv() (models.Env, error) {
|
||||||
|
var env models.Env
|
||||||
|
|
||||||
|
query := fmt.Sprintf("SELECT id, env, hash, created_at, updated_at FROM %s LIMIT 1", KeySpace+"."+models.Collections.Env)
|
||||||
|
err := p.db.Query(query).Consistency(gocql.One).Scan(&env.ID, &env.EnvData, &env.Hash, &env.CreatedAt, &env.UpdatedAt)
|
||||||
|
if err != nil {
|
||||||
|
return env, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return env, nil
|
||||||
|
}
|
168
server/db/providers/cassandradb/provider.go
Normal file
168
server/db/providers/cassandradb/provider.go
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
package cassandradb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"crypto/x509"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
|
"github.com/authorizerdev/authorizer/server/crypto"
|
||||||
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
|
"github.com/authorizerdev/authorizer/server/envstore"
|
||||||
|
"github.com/gocql/gocql"
|
||||||
|
cansandraDriver "github.com/gocql/gocql"
|
||||||
|
)
|
||||||
|
|
||||||
|
type provider struct {
|
||||||
|
db *cansandraDriver.Session
|
||||||
|
}
|
||||||
|
|
||||||
|
// KeySpace for the cassandra database
|
||||||
|
var KeySpace string
|
||||||
|
|
||||||
|
// NewProvider to initialize arangodb connection
|
||||||
|
func NewProvider() (*provider, error) {
|
||||||
|
dbURL := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseURL)
|
||||||
|
if dbURL == "" {
|
||||||
|
dbURL = envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseHost)
|
||||||
|
if envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabasePort) != "" {
|
||||||
|
dbURL = fmt.Sprintf("%s:%s", dbURL, envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabasePort))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KeySpace = envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseName)
|
||||||
|
clusterURL := []string{}
|
||||||
|
if strings.Contains(dbURL, ",") {
|
||||||
|
clusterURL = strings.Split(dbURL, ",")
|
||||||
|
} else {
|
||||||
|
clusterURL = append(clusterURL, dbURL)
|
||||||
|
}
|
||||||
|
cassandraClient := cansandraDriver.NewCluster(clusterURL...)
|
||||||
|
if envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseUsername) != "" && envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabasePassword) != "" {
|
||||||
|
cassandraClient.Authenticator = &cansandraDriver.PasswordAuthenticator{
|
||||||
|
Username: envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseUsername),
|
||||||
|
Password: envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabasePassword),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseCert) != "" && envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseCACert) != "" && envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseCertKey) != "" {
|
||||||
|
certString, err := crypto.DecryptB64(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseCert))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
keyString, err := crypto.DecryptB64(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseCertKey))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
caString, err := crypto.DecryptB64(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseCACert))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
cert, err := tls.X509KeyPair([]byte(certString), []byte(keyString))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
caCertPool := x509.NewCertPool()
|
||||||
|
caCertPool.AppendCertsFromPEM([]byte(caString))
|
||||||
|
|
||||||
|
cassandraClient.SslOpts = &cansandraDriver.SslOptions{
|
||||||
|
Config: &tls.Config{
|
||||||
|
Certificates: []tls.Certificate{cert},
|
||||||
|
RootCAs: caCertPool,
|
||||||
|
InsecureSkipVerify: true,
|
||||||
|
},
|
||||||
|
EnableHostVerification: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cassandraClient.RetryPolicy = &cansandraDriver.SimpleRetryPolicy{
|
||||||
|
NumRetries: 3,
|
||||||
|
}
|
||||||
|
cassandraClient.Consistency = gocql.LocalQuorum
|
||||||
|
|
||||||
|
session, err := cassandraClient.CreateSession()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note for astra keyspaces can only be created from there console
|
||||||
|
// https://docs.datastax.com/en/astra/docs/datastax-astra-faq.html#_i_am_trying_to_create_a_keyspace_in_the_cql_shell_and_i_am_running_into_an_error_how_do_i_fix_this
|
||||||
|
getKeyspaceQuery := fmt.Sprintf("SELECT keyspace_name FROM system_schema.keyspaces;")
|
||||||
|
scanner := session.Query(getKeyspaceQuery).Iter().Scanner()
|
||||||
|
hasAuthorizerKeySpace := false
|
||||||
|
for scanner.Next() {
|
||||||
|
var keySpace string
|
||||||
|
err := scanner.Scan(&keySpace)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if keySpace == KeySpace {
|
||||||
|
hasAuthorizerKeySpace = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !hasAuthorizerKeySpace {
|
||||||
|
createKeySpaceQuery := fmt.Sprintf("CREATE KEYSPACE %s WITH REPLICATION = {'class': 'SimpleStrategy', 'replication_factor': 1};", KeySpace)
|
||||||
|
err = session.Query(createKeySpaceQuery).Exec()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure collections are present
|
||||||
|
envCollectionQuery := fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s.%s (id text, env text, hash text, updated_at bigint, created_at bigint, PRIMARY KEY (id))",
|
||||||
|
KeySpace, models.Collections.Env)
|
||||||
|
err = session.Query(envCollectionQuery).Exec()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
sessionCollectionQuery := fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s.%s (id text, user_id text, user_agent text, ip text, updated_at bigint, created_at bigint, PRIMARY KEY (id))", KeySpace, models.Collections.Session)
|
||||||
|
err = session.Query(sessionCollectionQuery).Exec()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
userCollectionQuery := fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s.%s (id text, email text, email_verified_at bigint, password text, signup_methods text, given_name text, family_name text, middle_name text, nickname text, gender text, birthdate text, phone_number text, phone_number_verified_at bigint, picture text, roles text, updated_at bigint, created_at bigint, revoked_timestamp bigint, PRIMARY KEY (id))", KeySpace, models.Collections.User)
|
||||||
|
err = session.Query(userCollectionQuery).Exec()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
userIndexQuery := fmt.Sprintf("CREATE INDEX IF NOT EXISTS authorizer_user_email ON %s.%s (email)", KeySpace, models.Collections.User)
|
||||||
|
err = session.Query(userIndexQuery).Exec()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// token is reserved keyword in cassandra, hence we need to use jwt_token
|
||||||
|
verificationRequestCollectionQuery := fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s.%s (id text, jwt_token text, identifier text, expires_at bigint, email text, nonce text, redirect_uri text, created_at bigint, updated_at bigint, PRIMARY KEY (id))", KeySpace, models.Collections.VerificationRequest)
|
||||||
|
err = session.Query(verificationRequestCollectionQuery).Exec()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
verificationRequestIndexQuery := fmt.Sprintf("CREATE INDEX IF NOT EXISTS authorizer_verification_request_email ON %s.%s (email)", KeySpace, models.Collections.VerificationRequest)
|
||||||
|
err = session.Query(verificationRequestIndexQuery).Exec()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
verificationRequestIndexQuery = fmt.Sprintf("CREATE INDEX IF NOT EXISTS authorizer_verification_request_identifier ON %s.%s (identifier)", KeySpace, models.Collections.VerificationRequest)
|
||||||
|
err = session.Query(verificationRequestIndexQuery).Exec()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
verificationRequestIndexQuery = fmt.Sprintf("CREATE INDEX IF NOT EXISTS authorizer_verification_request_jwt_token ON %s.%s (jwt_token)", KeySpace, models.Collections.VerificationRequest)
|
||||||
|
err = session.Query(verificationRequestIndexQuery).Exec()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &provider{
|
||||||
|
db: session,
|
||||||
|
}, err
|
||||||
|
}
|
36
server/db/providers/cassandradb/session.go
Normal file
36
server/db/providers/cassandradb/session.go
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
package cassandradb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AddSession to save session information in database
|
||||||
|
func (p *provider) AddSession(session models.Session) error {
|
||||||
|
if session.ID == "" {
|
||||||
|
session.ID = uuid.New().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
session.CreatedAt = time.Now().Unix()
|
||||||
|
session.UpdatedAt = time.Now().Unix()
|
||||||
|
|
||||||
|
insertSessionQuery := fmt.Sprintf("INSERT INTO %s (id, user_id, user_agent, ip, created_at, updated_at) VALUES ('%s', '%s', '%s', '%s', %d, %d)", KeySpace+"."+models.Collections.Session, session.ID, session.UserID, session.UserAgent, session.IP, session.CreatedAt, session.UpdatedAt)
|
||||||
|
err := p.db.Query(insertSessionQuery).Exec()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteSession to delete session information from database
|
||||||
|
func (p *provider) DeleteSession(userId string) error {
|
||||||
|
deleteSessionQuery := fmt.Sprintf("DELETE FROM %s WHERE user_id = '%s'", KeySpace+"."+models.Collections.Session, userId)
|
||||||
|
err := p.db.Query(deleteSessionQuery).Exec()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
189
server/db/providers/cassandradb/user.go
Normal file
189
server/db/providers/cassandradb/user.go
Normal file
@@ -0,0 +1,189 @@
|
|||||||
|
package cassandradb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
|
"github.com/authorizerdev/authorizer/server/envstore"
|
||||||
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
|
"github.com/gocql/gocql"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AddUser to save user information in database
|
||||||
|
func (p *provider) AddUser(user models.User) (models.User, error) {
|
||||||
|
if user.ID == "" {
|
||||||
|
user.ID = uuid.New().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
if user.Roles == "" {
|
||||||
|
user.Roles = strings.Join(envstore.EnvStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyDefaultRoles), ",")
|
||||||
|
}
|
||||||
|
|
||||||
|
user.CreatedAt = time.Now().Unix()
|
||||||
|
user.UpdatedAt = time.Now().Unix()
|
||||||
|
|
||||||
|
bytes, err := json.Marshal(user)
|
||||||
|
if err != nil {
|
||||||
|
return user, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// use decoder instead of json.Unmarshall, because it converts int64 -> float64 after unmarshalling
|
||||||
|
decoder := json.NewDecoder(strings.NewReader(string(bytes)))
|
||||||
|
decoder.UseNumber()
|
||||||
|
userMap := map[string]interface{}{}
|
||||||
|
err = decoder.Decode(&userMap)
|
||||||
|
if err != nil {
|
||||||
|
return user, err
|
||||||
|
}
|
||||||
|
|
||||||
|
fields := "("
|
||||||
|
values := "("
|
||||||
|
for key, value := range userMap {
|
||||||
|
if value != nil {
|
||||||
|
if key == "_id" {
|
||||||
|
fields += "id,"
|
||||||
|
} else {
|
||||||
|
fields += key + ","
|
||||||
|
}
|
||||||
|
|
||||||
|
valueType := reflect.TypeOf(value)
|
||||||
|
if valueType.Name() == "string" {
|
||||||
|
values += fmt.Sprintf("'%s',", value.(string))
|
||||||
|
} else {
|
||||||
|
values += fmt.Sprintf("%v,", value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fields = fields[:len(fields)-1] + ")"
|
||||||
|
values = values[:len(values)-1] + ")"
|
||||||
|
|
||||||
|
query := fmt.Sprintf("INSERT INTO %s %s VALUES %s IF NOT EXISTS", KeySpace+"."+models.Collections.User, fields, values)
|
||||||
|
|
||||||
|
err = p.db.Query(query).Exec()
|
||||||
|
if err != nil {
|
||||||
|
return user, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return user, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateUser to update user information in database
|
||||||
|
func (p *provider) UpdateUser(user models.User) (models.User, error) {
|
||||||
|
user.UpdatedAt = time.Now().Unix()
|
||||||
|
|
||||||
|
bytes, err := json.Marshal(user)
|
||||||
|
if err != nil {
|
||||||
|
return user, err
|
||||||
|
}
|
||||||
|
// use decoder instead of json.Unmarshall, because it converts int64 -> float64 after unmarshalling
|
||||||
|
decoder := json.NewDecoder(strings.NewReader(string(bytes)))
|
||||||
|
decoder.UseNumber()
|
||||||
|
userMap := map[string]interface{}{}
|
||||||
|
err = decoder.Decode(&userMap)
|
||||||
|
if err != nil {
|
||||||
|
return user, err
|
||||||
|
}
|
||||||
|
|
||||||
|
updateFields := ""
|
||||||
|
for key, value := range userMap {
|
||||||
|
if value != nil && key != "_id" {
|
||||||
|
}
|
||||||
|
|
||||||
|
if key == "_id" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if value == nil {
|
||||||
|
updateFields += fmt.Sprintf("%s = null,", key)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
valueType := reflect.TypeOf(value)
|
||||||
|
if valueType.Name() == "string" {
|
||||||
|
updateFields += fmt.Sprintf("%s = '%s', ", key, value.(string))
|
||||||
|
} else {
|
||||||
|
updateFields += fmt.Sprintf("%s = %v, ", key, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updateFields = strings.Trim(updateFields, " ")
|
||||||
|
updateFields = strings.TrimSuffix(updateFields, ",")
|
||||||
|
|
||||||
|
query := fmt.Sprintf("UPDATE %s SET %s WHERE id = '%s'", KeySpace+"."+models.Collections.User, updateFields, user.ID)
|
||||||
|
|
||||||
|
err = p.db.Query(query).Exec()
|
||||||
|
if err != nil {
|
||||||
|
return user, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return user, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteUser to delete user information from database
|
||||||
|
func (p *provider) DeleteUser(user models.User) error {
|
||||||
|
query := fmt.Sprintf("DELETE FROM %s WHERE id = '%s'", KeySpace+"."+models.Collections.User, user.ID)
|
||||||
|
err := p.db.Query(query).Exec()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListUsers to get list of users from database
|
||||||
|
func (p *provider) ListUsers(pagination model.Pagination) (*model.Users, error) {
|
||||||
|
responseUsers := []*model.User{}
|
||||||
|
paginationClone := pagination
|
||||||
|
totalCountQuery := fmt.Sprintf(`SELECT COUNT(*) FROM %s`, KeySpace+"."+models.Collections.User)
|
||||||
|
err := p.db.Query(totalCountQuery).Consistency(gocql.One).Scan(&paginationClone.Total)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// there is no offset in cassandra
|
||||||
|
// so we fetch till limit + offset
|
||||||
|
// and return the results from offset to limit
|
||||||
|
query := fmt.Sprintf("SELECT id, email, email_verified_at, password, signup_methods, given_name, family_name, middle_name, nickname, birthdate, phone_number, phone_number_verified_at, picture, roles, revoked_timestamp, created_at, updated_at FROM %s LIMIT %d", KeySpace+"."+models.Collections.User, pagination.Limit+pagination.Offset)
|
||||||
|
|
||||||
|
scanner := p.db.Query(query).Iter().Scanner()
|
||||||
|
counter := int64(0)
|
||||||
|
for scanner.Next() {
|
||||||
|
if counter >= pagination.Offset {
|
||||||
|
var user models.User
|
||||||
|
err := scanner.Scan(&user.ID, &user.Email, &user.EmailVerifiedAt, &user.Password, &user.SignupMethods, &user.GivenName, &user.FamilyName, &user.MiddleName, &user.Nickname, &user.Birthdate, &user.PhoneNumber, &user.PhoneNumberVerifiedAt, &user.Picture, &user.Roles, &user.RevokedTimestamp, &user.CreatedAt, &user.UpdatedAt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
responseUsers = append(responseUsers, user.AsAPIUser())
|
||||||
|
}
|
||||||
|
counter++
|
||||||
|
}
|
||||||
|
return &model.Users{
|
||||||
|
Users: responseUsers,
|
||||||
|
Pagination: &paginationClone,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUserByEmail to get user information from database using email address
|
||||||
|
func (p *provider) GetUserByEmail(email string) (models.User, error) {
|
||||||
|
var user models.User
|
||||||
|
query := fmt.Sprintf("SELECT id, email, email_verified_at, password, signup_methods, given_name, family_name, middle_name, nickname, birthdate, phone_number, phone_number_verified_at, picture, roles, revoked_timestamp, created_at, updated_at FROM %s WHERE email = '%s' LIMIT 1", KeySpace+"."+models.Collections.User, email)
|
||||||
|
err := p.db.Query(query).Consistency(gocql.One).Scan(&user.ID, &user.Email, &user.EmailVerifiedAt, &user.Password, &user.SignupMethods, &user.GivenName, &user.FamilyName, &user.MiddleName, &user.Nickname, &user.Birthdate, &user.PhoneNumber, &user.PhoneNumberVerifiedAt, &user.Picture, &user.Roles, &user.RevokedTimestamp, &user.CreatedAt, &user.UpdatedAt)
|
||||||
|
if err != nil {
|
||||||
|
return user, err
|
||||||
|
}
|
||||||
|
return user, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUserByID to get user information from database using user ID
|
||||||
|
func (p *provider) GetUserByID(id string) (models.User, error) {
|
||||||
|
var user models.User
|
||||||
|
query := fmt.Sprintf("SELECT id, email, email_verified_at, password, signup_methods, given_name, family_name, middle_name, nickname, birthdate, phone_number, phone_number_verified_at, picture, roles, revoked_timestamp, created_at, updated_at FROM %s WHERE id = '%s' LIMIT 1", KeySpace+"."+models.Collections.User, id)
|
||||||
|
err := p.db.Query(query).Consistency(gocql.One).Scan(&user.ID, &user.Email, &user.EmailVerifiedAt, &user.Password, &user.SignupMethods, &user.GivenName, &user.FamilyName, &user.MiddleName, &user.Nickname, &user.Birthdate, &user.PhoneNumber, &user.PhoneNumberVerifiedAt, &user.Picture, &user.Roles, &user.RevokedTimestamp, &user.CreatedAt, &user.UpdatedAt)
|
||||||
|
if err != nil {
|
||||||
|
return user, err
|
||||||
|
}
|
||||||
|
return user, nil
|
||||||
|
}
|
99
server/db/providers/cassandradb/verification_requests.go
Normal file
99
server/db/providers/cassandradb/verification_requests.go
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
package cassandradb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
|
"github.com/gocql/gocql"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AddVerification to save verification request in database
|
||||||
|
func (p *provider) AddVerificationRequest(verificationRequest models.VerificationRequest) (models.VerificationRequest, error) {
|
||||||
|
if verificationRequest.ID == "" {
|
||||||
|
verificationRequest.ID = uuid.New().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
verificationRequest.CreatedAt = time.Now().Unix()
|
||||||
|
verificationRequest.UpdatedAt = time.Now().Unix()
|
||||||
|
|
||||||
|
query := fmt.Sprintf("INSERT INTO %s (id, jwt_token, identifier, expires_at, email, nonce, redirect_uri, created_at, updated_at) VALUES ('%s', '%s', '%s', %d, '%s', '%s', '%s', %d, %d)", KeySpace+"."+models.Collections.VerificationRequest, verificationRequest.ID, verificationRequest.Token, verificationRequest.Identifier, verificationRequest.ExpiresAt, verificationRequest.Email, verificationRequest.Nonce, verificationRequest.RedirectURI, verificationRequest.CreatedAt, verificationRequest.UpdatedAt)
|
||||||
|
err := p.db.Query(query).Exec()
|
||||||
|
if err != nil {
|
||||||
|
return verificationRequest, err
|
||||||
|
}
|
||||||
|
return verificationRequest, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetVerificationRequestByToken to get verification request from database using token
|
||||||
|
func (p *provider) GetVerificationRequestByToken(token string) (models.VerificationRequest, error) {
|
||||||
|
var verificationRequest models.VerificationRequest
|
||||||
|
query := fmt.Sprintf(`SELECT id, jwt_token, identifier, expires_at, email, nonce, redirect_uri, created_at, updated_at FROM %s WHERE jwt_token = '%s' LIMIT 1`, KeySpace+"."+models.Collections.VerificationRequest, token)
|
||||||
|
|
||||||
|
err := p.db.Query(query).Consistency(gocql.One).Scan(&verificationRequest.ID, &verificationRequest.Token, &verificationRequest.Identifier, &verificationRequest.ExpiresAt, &verificationRequest.Email, &verificationRequest.Nonce, &verificationRequest.RedirectURI, &verificationRequest.CreatedAt, &verificationRequest.UpdatedAt)
|
||||||
|
if err != nil {
|
||||||
|
return verificationRequest, err
|
||||||
|
}
|
||||||
|
return verificationRequest, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetVerificationRequestByEmail to get verification request by email from database
|
||||||
|
func (p *provider) GetVerificationRequestByEmail(email string, identifier string) (models.VerificationRequest, error) {
|
||||||
|
var verificationRequest models.VerificationRequest
|
||||||
|
query := fmt.Sprintf(`SELECT id, jwt_token, identifier, expires_at, email, nonce, redirect_uri, created_at, updated_at FROM %s WHERE email = '%s' AND identifier = '%s' LIMIT 1 ALLOW FILTERING`, KeySpace+"."+models.Collections.VerificationRequest, email, identifier)
|
||||||
|
|
||||||
|
err := p.db.Query(query).Consistency(gocql.One).Scan(&verificationRequest.ID, &verificationRequest.Token, &verificationRequest.Identifier, &verificationRequest.ExpiresAt, &verificationRequest.Email, &verificationRequest.Nonce, &verificationRequest.RedirectURI, &verificationRequest.CreatedAt, &verificationRequest.UpdatedAt)
|
||||||
|
if err != nil {
|
||||||
|
return verificationRequest, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return verificationRequest, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListVerificationRequests to get list of verification requests from database
|
||||||
|
func (p *provider) ListVerificationRequests(pagination model.Pagination) (*model.VerificationRequests, error) {
|
||||||
|
var verificationRequests []*model.VerificationRequest
|
||||||
|
|
||||||
|
paginationClone := pagination
|
||||||
|
totalCountQuery := fmt.Sprintf(`SELECT COUNT(*) FROM %s`, KeySpace+"."+models.Collections.VerificationRequest)
|
||||||
|
err := p.db.Query(totalCountQuery).Consistency(gocql.One).Scan(&paginationClone.Total)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// there is no offset in cassandra
|
||||||
|
// so we fetch till limit + offset
|
||||||
|
// and return the results from offset to limit
|
||||||
|
query := fmt.Sprintf(`SELECT id, jwt_token, identifier, expires_at, email, nonce, redirect_uri, created_at, updated_at FROM %s LIMIT %d`, KeySpace+"."+models.Collections.VerificationRequest, pagination.Limit+pagination.Offset)
|
||||||
|
|
||||||
|
scanner := p.db.Query(query).Iter().Scanner()
|
||||||
|
counter := int64(0)
|
||||||
|
for scanner.Next() {
|
||||||
|
if counter >= pagination.Offset {
|
||||||
|
var verificationRequest models.VerificationRequest
|
||||||
|
err := scanner.Scan(&verificationRequest.ID, &verificationRequest.Token, &verificationRequest.Identifier, &verificationRequest.ExpiresAt, &verificationRequest.Email, &verificationRequest.Nonce, &verificationRequest.RedirectURI, &verificationRequest.CreatedAt, &verificationRequest.UpdatedAt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
verificationRequests = append(verificationRequests, verificationRequest.AsAPIVerificationRequest())
|
||||||
|
}
|
||||||
|
counter++
|
||||||
|
}
|
||||||
|
|
||||||
|
return &model.VerificationRequests{
|
||||||
|
VerificationRequests: verificationRequests,
|
||||||
|
Pagination: &paginationClone,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteVerificationRequest to delete verification request from database
|
||||||
|
func (p *provider) DeleteVerificationRequest(verificationRequest models.VerificationRequest) error {
|
||||||
|
query := fmt.Sprintf("DELETE FROM %s WHERE id = '%s'", KeySpace+"."+models.Collections.VerificationRequest, verificationRequest.ID)
|
||||||
|
err := p.db.Query(query).Exec()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
@@ -2,7 +2,6 @@ package mongodb
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/db/models"
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
@@ -23,7 +22,6 @@ func (p *provider) AddEnv(env models.Env) (models.Env, error) {
|
|||||||
configCollection := p.db.Collection(models.Collections.Env, options.Collection())
|
configCollection := p.db.Collection(models.Collections.Env, options.Collection())
|
||||||
_, err := configCollection.InsertOne(nil, env)
|
_, err := configCollection.InsertOne(nil, env)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error adding config:", err)
|
|
||||||
return env, err
|
return env, err
|
||||||
}
|
}
|
||||||
return env, nil
|
return env, nil
|
||||||
@@ -35,7 +33,6 @@ func (p *provider) UpdateEnv(env models.Env) (models.Env, error) {
|
|||||||
configCollection := p.db.Collection(models.Collections.Env, options.Collection())
|
configCollection := p.db.Collection(models.Collections.Env, options.Collection())
|
||||||
_, err := configCollection.UpdateOne(nil, bson.M{"_id": bson.M{"$eq": env.ID}}, bson.M{"$set": env}, options.MergeUpdateOptions())
|
_, err := configCollection.UpdateOne(nil, bson.M{"_id": bson.M{"$eq": env.ID}}, bson.M{"$set": env}, options.MergeUpdateOptions())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error updating config:", err)
|
|
||||||
return env, err
|
return env, err
|
||||||
}
|
}
|
||||||
return env, nil
|
return env, nil
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
package mongodb
|
package mongodb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/db/models"
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
@@ -22,7 +21,6 @@ func (p *provider) AddSession(session models.Session) error {
|
|||||||
sessionCollection := p.db.Collection(models.Collections.Session, options.Collection())
|
sessionCollection := p.db.Collection(models.Collections.Session, options.Collection())
|
||||||
_, err := sessionCollection.InsertOne(nil, session)
|
_, err := sessionCollection.InsertOne(nil, session)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(`error saving session`, err)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@@ -33,7 +31,6 @@ func (p *provider) DeleteSession(userId string) error {
|
|||||||
sessionCollection := p.db.Collection(models.Collections.Session, options.Collection())
|
sessionCollection := p.db.Collection(models.Collections.Session, options.Collection())
|
||||||
_, err := sessionCollection.DeleteMany(nil, bson.M{"user_id": userId}, options.Delete())
|
_, err := sessionCollection.DeleteMany(nil, bson.M{"user_id": userId}, options.Delete())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error deleting session:", err)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
package mongodb
|
package mongodb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -29,7 +28,6 @@ func (p *provider) AddUser(user models.User) (models.User, error) {
|
|||||||
userCollection := p.db.Collection(models.Collections.User, options.Collection())
|
userCollection := p.db.Collection(models.Collections.User, options.Collection())
|
||||||
_, err := userCollection.InsertOne(nil, user)
|
_, err := userCollection.InsertOne(nil, user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error adding user:", err)
|
|
||||||
return user, err
|
return user, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,7 +40,6 @@ func (p *provider) UpdateUser(user models.User) (models.User, error) {
|
|||||||
userCollection := p.db.Collection(models.Collections.User, options.Collection())
|
userCollection := p.db.Collection(models.Collections.User, options.Collection())
|
||||||
_, err := userCollection.UpdateOne(nil, bson.M{"_id": bson.M{"$eq": user.ID}}, bson.M{"$set": user}, options.MergeUpdateOptions())
|
_, err := userCollection.UpdateOne(nil, bson.M{"_id": bson.M{"$eq": user.ID}}, bson.M{"$set": user}, options.MergeUpdateOptions())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error updating user:", err)
|
|
||||||
return user, err
|
return user, err
|
||||||
}
|
}
|
||||||
return user, nil
|
return user, nil
|
||||||
@@ -53,7 +50,6 @@ func (p *provider) DeleteUser(user models.User) error {
|
|||||||
userCollection := p.db.Collection(models.Collections.User, options.Collection())
|
userCollection := p.db.Collection(models.Collections.User, options.Collection())
|
||||||
_, err := userCollection.DeleteOne(nil, bson.M{"_id": user.ID}, options.Delete())
|
_, err := userCollection.DeleteOne(nil, bson.M{"_id": user.ID}, options.Delete())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error deleting user:", err)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,7 +70,6 @@ func (p *provider) ListUsers(pagination model.Pagination) (*model.Users, error)
|
|||||||
userCollection := p.db.Collection(models.Collections.User, options.Collection())
|
userCollection := p.db.Collection(models.Collections.User, options.Collection())
|
||||||
count, err := userCollection.CountDocuments(nil, bson.M{}, options.Count())
|
count, err := userCollection.CountDocuments(nil, bson.M{}, options.Count())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error getting total users:", err)
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,7 +77,6 @@ func (p *provider) ListUsers(pagination model.Pagination) (*model.Users, error)
|
|||||||
|
|
||||||
cursor, err := userCollection.Find(nil, bson.M{}, opts)
|
cursor, err := userCollection.Find(nil, bson.M{}, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error getting users:", err)
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer cursor.Close(nil)
|
defer cursor.Close(nil)
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
package mongodb
|
package mongodb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/db/models"
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
@@ -22,7 +21,6 @@ func (p *provider) AddVerificationRequest(verificationRequest models.Verificatio
|
|||||||
verificationRequestCollection := p.db.Collection(models.Collections.VerificationRequest, options.Collection())
|
verificationRequestCollection := p.db.Collection(models.Collections.VerificationRequest, options.Collection())
|
||||||
_, err := verificationRequestCollection.InsertOne(nil, verificationRequest)
|
_, err := verificationRequestCollection.InsertOne(nil, verificationRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error saving verification record:", err)
|
|
||||||
return verificationRequest, err
|
return verificationRequest, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -73,7 +71,6 @@ func (p *provider) ListVerificationRequests(pagination model.Pagination) (*model
|
|||||||
|
|
||||||
cursor, err := verificationRequestCollection.Find(nil, bson.M{}, opts)
|
cursor, err := verificationRequestCollection.Find(nil, bson.M{}, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error getting verification requests:", err)
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer cursor.Close(nil)
|
defer cursor.Close(nil)
|
||||||
@@ -98,7 +95,6 @@ func (p *provider) DeleteVerificationRequest(verificationRequest models.Verifica
|
|||||||
verificationRequestCollection := p.db.Collection(models.Collections.VerificationRequest, options.Collection())
|
verificationRequestCollection := p.db.Collection(models.Collections.VerificationRequest, options.Collection())
|
||||||
_, err := verificationRequestCollection.DeleteOne(nil, bson.M{"_id": verificationRequest.ID}, options.Delete())
|
_, err := verificationRequestCollection.DeleteOne(nil, bson.M{"_id": verificationRequest.ID}, options.Delete())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error deleting verification request::", err)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
32
server/db/providers/provider_template/env.go
Normal file
32
server/db/providers/provider_template/env.go
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
package provider_template
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AddEnv to save environment information in database
|
||||||
|
func (p *provider) AddEnv(env models.Env) (models.Env, error) {
|
||||||
|
if env.ID == "" {
|
||||||
|
env.ID = uuid.New().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
env.CreatedAt = time.Now().Unix()
|
||||||
|
env.UpdatedAt = time.Now().Unix()
|
||||||
|
return env, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateEnv to update environment information in database
|
||||||
|
func (p *provider) UpdateEnv(env models.Env) (models.Env, error) {
|
||||||
|
env.UpdatedAt = time.Now().Unix()
|
||||||
|
return env, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetEnv to get environment information from database
|
||||||
|
func (p *provider) GetEnv() (models.Env, error) {
|
||||||
|
var env models.Env
|
||||||
|
|
||||||
|
return env, nil
|
||||||
|
}
|
20
server/db/providers/provider_template/provider.go
Normal file
20
server/db/providers/provider_template/provider.go
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package provider_template
|
||||||
|
|
||||||
|
import (
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO change following provider to new db provider
|
||||||
|
type provider struct {
|
||||||
|
db *gorm.DB
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewProvider returns a new SQL provider
|
||||||
|
// TODO change following provider to new db provider
|
||||||
|
func NewProvider() (*provider, error) {
|
||||||
|
var sqlDB *gorm.DB
|
||||||
|
|
||||||
|
return &provider{
|
||||||
|
db: sqlDB,
|
||||||
|
}, nil
|
||||||
|
}
|
24
server/db/providers/provider_template/session.go
Normal file
24
server/db/providers/provider_template/session.go
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package provider_template
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AddSession to save session information in database
|
||||||
|
func (p *provider) AddSession(session models.Session) error {
|
||||||
|
if session.ID == "" {
|
||||||
|
session.ID = uuid.New().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
session.CreatedAt = time.Now().Unix()
|
||||||
|
session.UpdatedAt = time.Now().Unix()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteSession to delete session information from database
|
||||||
|
func (p *provider) DeleteSession(userId string) error {
|
||||||
|
return nil
|
||||||
|
}
|
58
server/db/providers/provider_template/user.go
Normal file
58
server/db/providers/provider_template/user.go
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
package provider_template
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
|
"github.com/authorizerdev/authorizer/server/envstore"
|
||||||
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AddUser to save user information in database
|
||||||
|
func (p *provider) AddUser(user models.User) (models.User, error) {
|
||||||
|
if user.ID == "" {
|
||||||
|
user.ID = uuid.New().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
if user.Roles == "" {
|
||||||
|
user.Roles = strings.Join(envstore.EnvStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyDefaultRoles), ",")
|
||||||
|
}
|
||||||
|
|
||||||
|
user.CreatedAt = time.Now().Unix()
|
||||||
|
user.UpdatedAt = time.Now().Unix()
|
||||||
|
|
||||||
|
return user, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateUser to update user information in database
|
||||||
|
func (p *provider) UpdateUser(user models.User) (models.User, error) {
|
||||||
|
user.UpdatedAt = time.Now().Unix()
|
||||||
|
return user, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteUser to delete user information from database
|
||||||
|
func (p *provider) DeleteUser(user models.User) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListUsers to get list of users from database
|
||||||
|
func (p *provider) ListUsers(pagination model.Pagination) (*model.Users, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUserByEmail to get user information from database using email address
|
||||||
|
func (p *provider) GetUserByEmail(email string) (models.User, error) {
|
||||||
|
var user models.User
|
||||||
|
|
||||||
|
return user, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUserByID to get user information from database using user ID
|
||||||
|
func (p *provider) GetUserByID(id string) (models.User, error) {
|
||||||
|
var user models.User
|
||||||
|
|
||||||
|
return user, nil
|
||||||
|
}
|
@@ -0,0 +1,45 @@
|
|||||||
|
package provider_template
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AddVerification to save verification request in database
|
||||||
|
func (p *provider) AddVerificationRequest(verificationRequest models.VerificationRequest) (models.VerificationRequest, error) {
|
||||||
|
if verificationRequest.ID == "" {
|
||||||
|
verificationRequest.ID = uuid.New().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
verificationRequest.CreatedAt = time.Now().Unix()
|
||||||
|
verificationRequest.UpdatedAt = time.Now().Unix()
|
||||||
|
|
||||||
|
return verificationRequest, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetVerificationRequestByToken to get verification request from database using token
|
||||||
|
func (p *provider) GetVerificationRequestByToken(token string) (models.VerificationRequest, error) {
|
||||||
|
var verificationRequest models.VerificationRequest
|
||||||
|
|
||||||
|
return verificationRequest, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetVerificationRequestByEmail to get verification request by email from database
|
||||||
|
func (p *provider) GetVerificationRequestByEmail(email string, identifier string) (models.VerificationRequest, error) {
|
||||||
|
var verificationRequest models.VerificationRequest
|
||||||
|
|
||||||
|
return verificationRequest, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListVerificationRequests to get list of verification requests from database
|
||||||
|
func (p *provider) ListVerificationRequests(pagination model.Pagination) (*model.VerificationRequests, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteVerificationRequest to delete verification request from database
|
||||||
|
func (p *provider) DeleteVerificationRequest(verificationRequest models.VerificationRequest) error {
|
||||||
|
return nil
|
||||||
|
}
|
@@ -1,7 +1,6 @@
|
|||||||
package sql
|
package sql
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/db/models"
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
@@ -20,7 +19,6 @@ func (p *provider) AddEnv(env models.Env) (models.Env, error) {
|
|||||||
|
|
||||||
result := p.db.Create(&env)
|
result := p.db.Create(&env)
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
log.Println("error adding config:", result.Error)
|
|
||||||
return env, result.Error
|
return env, result.Error
|
||||||
}
|
}
|
||||||
return env, nil
|
return env, nil
|
||||||
@@ -32,7 +30,6 @@ func (p *provider) UpdateEnv(env models.Env) (models.Env, error) {
|
|||||||
result := p.db.Save(&env)
|
result := p.db.Save(&env)
|
||||||
|
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
log.Println("error updating config:", result.Error)
|
|
||||||
return env, result.Error
|
return env, result.Error
|
||||||
}
|
}
|
||||||
return env, nil
|
return env, nil
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
package sql
|
package sql
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/db/models"
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
@@ -23,7 +22,6 @@ func (p *provider) AddSession(session models.Session) error {
|
|||||||
DoNothing: true,
|
DoNothing: true,
|
||||||
}).Create(&session)
|
}).Create(&session)
|
||||||
if res.Error != nil {
|
if res.Error != nil {
|
||||||
log.Println(`error saving session`, res.Error)
|
|
||||||
return res.Error
|
return res.Error
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@@ -34,7 +32,6 @@ func (p *provider) DeleteSession(userId string) error {
|
|||||||
result := p.db.Where("user_id = ?", userId).Delete(&models.Session{})
|
result := p.db.Where("user_id = ?", userId).Delete(&models.Session{})
|
||||||
|
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
log.Println(`error deleting session:`, result.Error)
|
|
||||||
return result.Error
|
return result.Error
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
package sql
|
package sql
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -33,7 +32,6 @@ func (p *provider) AddUser(user models.User) (models.User, error) {
|
|||||||
}).Create(&user)
|
}).Create(&user)
|
||||||
|
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
log.Println("error adding user:", result.Error)
|
|
||||||
return user, result.Error
|
return user, result.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,7 +45,6 @@ func (p *provider) UpdateUser(user models.User) (models.User, error) {
|
|||||||
result := p.db.Save(&user)
|
result := p.db.Save(&user)
|
||||||
|
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
log.Println("error updating user:", result.Error)
|
|
||||||
return user, result.Error
|
return user, result.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,7 +56,6 @@ func (p *provider) DeleteUser(user models.User) error {
|
|||||||
result := p.db.Delete(&user)
|
result := p.db.Delete(&user)
|
||||||
|
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
log.Println(`error deleting user:`, result.Error)
|
|
||||||
return result.Error
|
return result.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,7 +67,6 @@ func (p *provider) ListUsers(pagination model.Pagination) (*model.Users, error)
|
|||||||
var users []models.User
|
var users []models.User
|
||||||
result := p.db.Limit(int(pagination.Limit)).Offset(int(pagination.Offset)).Order("created_at DESC").Find(&users)
|
result := p.db.Limit(int(pagination.Limit)).Offset(int(pagination.Offset)).Order("created_at DESC").Find(&users)
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
log.Println("error getting users:", result.Error)
|
|
||||||
return nil, result.Error
|
return nil, result.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
package sql
|
package sql
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/db/models"
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
@@ -25,7 +24,6 @@ func (p *provider) AddVerificationRequest(verificationRequest models.Verificatio
|
|||||||
}).Create(&verificationRequest)
|
}).Create(&verificationRequest)
|
||||||
|
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
log.Println(`error saving verification request record`, result.Error)
|
|
||||||
return verificationRequest, result.Error
|
return verificationRequest, result.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,7 +36,6 @@ func (p *provider) GetVerificationRequestByToken(token string) (models.Verificat
|
|||||||
result := p.db.Where("token = ?", token).First(&verificationRequest)
|
result := p.db.Where("token = ?", token).First(&verificationRequest)
|
||||||
|
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
log.Println(`error getting verification request:`, result.Error)
|
|
||||||
return verificationRequest, result.Error
|
return verificationRequest, result.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,7 +49,6 @@ func (p *provider) GetVerificationRequestByEmail(email string, identifier string
|
|||||||
result := p.db.Where("email = ? AND identifier = ?", email, identifier).First(&verificationRequest)
|
result := p.db.Where("email = ? AND identifier = ?", email, identifier).First(&verificationRequest)
|
||||||
|
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
log.Println(`error getting verification token:`, result.Error)
|
|
||||||
return verificationRequest, result.Error
|
return verificationRequest, result.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,7 +61,6 @@ func (p *provider) ListVerificationRequests(pagination model.Pagination) (*model
|
|||||||
|
|
||||||
result := p.db.Limit(int(pagination.Limit)).Offset(int(pagination.Offset)).Order("created_at DESC").Find(&verificationRequests)
|
result := p.db.Limit(int(pagination.Limit)).Offset(int(pagination.Offset)).Order("created_at DESC").Find(&verificationRequests)
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
log.Println("error getting verification requests:", result.Error)
|
|
||||||
return nil, result.Error
|
return nil, result.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,7 +89,6 @@ func (p *provider) DeleteVerificationRequest(verificationRequest models.Verifica
|
|||||||
result := p.db.Delete(&verificationRequest)
|
result := p.db.Delete(&verificationRequest)
|
||||||
|
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
log.Println(`error deleting verification request:`, result.Error)
|
|
||||||
return result.Error
|
return result.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -4,13 +4,14 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"log"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
gomail "gopkg.in/mail.v2"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
"github.com/authorizerdev/authorizer/server/envstore"
|
||||||
gomail "gopkg.in/mail.v2"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// addEmailTemplate is used to add html template in email body
|
// addEmailTemplate is used to add html template in email body
|
||||||
@@ -46,7 +47,7 @@ func SendMail(to []string, Subject, bodyMessage string) error {
|
|||||||
d.TLSConfig = &tls.Config{InsecureSkipVerify: true}
|
d.TLSConfig = &tls.Config{InsecureSkipVerify: true}
|
||||||
}
|
}
|
||||||
if err := d.DialAndSend(m); err != nil {
|
if err := d.DialAndSend(m); err != nil {
|
||||||
log.Printf("smtp error: %s", err)
|
log.Debug("SMTP Failed: ", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
package email
|
package email
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
"github.com/authorizerdev/authorizer/server/envstore"
|
||||||
@@ -107,7 +107,7 @@ func InviteEmail(toEmail, token, verificationURL, redirectURI string) error {
|
|||||||
|
|
||||||
err := SendMail(Receiver, Subject, message)
|
err := SendMail(Receiver, Subject, message)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("=> error sending email:", err)
|
log.Warn("error sending email: ", err)
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
package email
|
package email
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
"github.com/authorizerdev/authorizer/server/envstore"
|
||||||
@@ -107,7 +107,7 @@ func SendVerificationMail(toEmail, token, hostname string) error {
|
|||||||
|
|
||||||
err := SendMail(Receiver, Subject, message)
|
err := SendMail(Receiver, Subject, message)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("=> error sending email:", err)
|
log.Warn("error sending email: ", err)
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
35
server/env/env.go
vendored
35
server/env/env.go
vendored
@@ -2,17 +2,17 @@ package env
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"log"
|
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"github.com/joho/godotenv"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/crypto"
|
"github.com/authorizerdev/authorizer/server/crypto"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
"github.com/authorizerdev/authorizer/server/envstore"
|
||||||
"github.com/authorizerdev/authorizer/server/utils"
|
"github.com/authorizerdev/authorizer/server/utils"
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/google/uuid"
|
|
||||||
"github.com/joho/godotenv"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// InitRequiredEnv to initialize EnvData and through error if required env are not present
|
// InitRequiredEnv to initialize EnvData and through error if required env are not present
|
||||||
@@ -29,15 +29,23 @@ func InitRequiredEnv() error {
|
|||||||
if envstore.ARG_ENV_FILE != nil && *envstore.ARG_ENV_FILE != "" {
|
if envstore.ARG_ENV_FILE != nil && *envstore.ARG_ENV_FILE != "" {
|
||||||
envPath = *envstore.ARG_ENV_FILE
|
envPath = *envstore.ARG_ENV_FILE
|
||||||
}
|
}
|
||||||
|
log.Info("env path: ", envPath)
|
||||||
|
|
||||||
err := godotenv.Load(envPath)
|
err := godotenv.Load(envPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("using OS env instead of %s file", envPath)
|
log.Info("using OS env instead of %s file", envPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
dbURL := os.Getenv(constants.EnvKeyDatabaseURL)
|
dbURL := os.Getenv(constants.EnvKeyDatabaseURL)
|
||||||
dbType := os.Getenv(constants.EnvKeyDatabaseType)
|
dbType := os.Getenv(constants.EnvKeyDatabaseType)
|
||||||
dbName := os.Getenv(constants.EnvKeyDatabaseName)
|
dbName := os.Getenv(constants.EnvKeyDatabaseName)
|
||||||
|
dbPort := os.Getenv(constants.EnvKeyDatabasePort)
|
||||||
|
dbHost := os.Getenv(constants.EnvKeyDatabaseHost)
|
||||||
|
dbUsername := os.Getenv(constants.EnvKeyDatabaseUsername)
|
||||||
|
dbPassword := os.Getenv(constants.EnvKeyDatabasePassword)
|
||||||
|
dbCert := os.Getenv(constants.EnvKeyDatabaseCert)
|
||||||
|
dbCertKey := os.Getenv(constants.EnvKeyDatabaseCertKey)
|
||||||
|
dbCACert := os.Getenv(constants.EnvKeyDatabaseCACert)
|
||||||
|
|
||||||
if strings.TrimSpace(dbType) == "" {
|
if strings.TrimSpace(dbType) == "" {
|
||||||
if envstore.ARG_DB_TYPE != nil && *envstore.ARG_DB_TYPE != "" {
|
if envstore.ARG_DB_TYPE != nil && *envstore.ARG_DB_TYPE != "" {
|
||||||
@@ -45,6 +53,7 @@ func InitRequiredEnv() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if dbType == "" {
|
if dbType == "" {
|
||||||
|
log.Debug("DATABASE_TYPE is not set")
|
||||||
return errors.New("invalid database type. DATABASE_TYPE is empty")
|
return errors.New("invalid database type. DATABASE_TYPE is empty")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -54,7 +63,8 @@ func InitRequiredEnv() error {
|
|||||||
dbURL = strings.TrimSpace(*envstore.ARG_DB_URL)
|
dbURL = strings.TrimSpace(*envstore.ARG_DB_URL)
|
||||||
}
|
}
|
||||||
|
|
||||||
if dbURL == "" {
|
if dbURL == "" && dbPort == "" && dbHost == "" && dbUsername == "" && dbPassword == "" {
|
||||||
|
log.Debug("DATABASE_URL is not set")
|
||||||
return errors.New("invalid database url. DATABASE_URL is required")
|
return errors.New("invalid database url. DATABASE_URL is required")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -69,6 +79,14 @@ func InitRequiredEnv() error {
|
|||||||
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabaseURL, dbURL)
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabaseURL, dbURL)
|
||||||
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabaseType, dbType)
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabaseType, dbType)
|
||||||
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabaseName, dbName)
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabaseName, dbName)
|
||||||
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabaseHost, dbHost)
|
||||||
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabasePort, dbPort)
|
||||||
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabaseUsername, dbUsername)
|
||||||
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabasePassword, dbPassword)
|
||||||
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabaseCert, dbCert)
|
||||||
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabaseCertKey, dbCertKey)
|
||||||
|
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabaseCACert, dbCACert)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,7 +94,7 @@ func InitRequiredEnv() error {
|
|||||||
func InitAllEnv() error {
|
func InitAllEnv() error {
|
||||||
envData, err := GetEnvData()
|
envData, err := GetEnvData()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("No env data found in db, using local clone of env data")
|
log.Info("No env data found in db, using local clone of env data")
|
||||||
// get clone of current store
|
// get clone of current store
|
||||||
envData = envstore.EnvStoreObj.GetEnvStoreClone()
|
envData = envstore.EnvStoreObj.GetEnvStoreClone()
|
||||||
}
|
}
|
||||||
@@ -103,7 +121,6 @@ func InitAllEnv() error {
|
|||||||
|
|
||||||
if envData.StringEnv[constants.EnvKeyEnv] == "production" {
|
if envData.StringEnv[constants.EnvKeyEnv] == "production" {
|
||||||
envData.BoolEnv[constants.EnvKeyIsProd] = true
|
envData.BoolEnv[constants.EnvKeyIsProd] = true
|
||||||
gin.SetMode(gin.ReleaseMode)
|
|
||||||
} else {
|
} else {
|
||||||
envData.BoolEnv[constants.EnvKeyIsProd] = false
|
envData.BoolEnv[constants.EnvKeyIsProd] = false
|
||||||
}
|
}
|
||||||
@@ -164,6 +181,7 @@ func InitAllEnv() error {
|
|||||||
} else {
|
} else {
|
||||||
algo = envData.StringEnv[constants.EnvKeyJwtType]
|
algo = envData.StringEnv[constants.EnvKeyJwtType]
|
||||||
if !crypto.IsHMACA(algo) && !crypto.IsRSA(algo) && !crypto.IsECDSA(algo) {
|
if !crypto.IsHMACA(algo) && !crypto.IsRSA(algo) && !crypto.IsECDSA(algo) {
|
||||||
|
log.Debug("Invalid JWT Algorithm")
|
||||||
return errors.New("invalid JWT_TYPE")
|
return errors.New("invalid JWT_TYPE")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -369,6 +387,7 @@ func InitAllEnv() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(roles) > 0 && len(defaultRoles) == 0 && len(defaultRolesEnv) > 0 {
|
if len(roles) > 0 && len(defaultRoles) == 0 && len(defaultRolesEnv) > 0 {
|
||||||
|
log.Debug("Default roles not found in roles list. It can be one from ROLES only")
|
||||||
return errors.New(`invalid DEFAULT_ROLE environment variable. It can be one from give ROLES environment variable value`)
|
return errors.New(`invalid DEFAULT_ROLE environment variable. It can be one from give ROLES environment variable value`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
17
server/env/persist_env.go
vendored
17
server/env/persist_env.go
vendored
@@ -2,12 +2,12 @@ package env
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"log"
|
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/crypto"
|
"github.com/authorizerdev/authorizer/server/crypto"
|
||||||
@@ -23,12 +23,14 @@ func GetEnvData() (envstore.Store, error) {
|
|||||||
env, err := db.Provider.GetEnv()
|
env, err := db.Provider.GetEnv()
|
||||||
// config not found in db
|
// config not found in db
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Error while getting env data from db: ", err)
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
encryptionKey := env.Hash
|
encryptionKey := env.Hash
|
||||||
decryptedEncryptionKey, err := crypto.DecryptB64(encryptionKey)
|
decryptedEncryptionKey, err := crypto.DecryptB64(encryptionKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Error while decrypting encryption key: ", err)
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,16 +38,19 @@ func GetEnvData() (envstore.Store, error) {
|
|||||||
|
|
||||||
b64DecryptedConfig, err := crypto.DecryptB64(env.EnvData)
|
b64DecryptedConfig, err := crypto.DecryptB64(env.EnvData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Error while decrypting env data from B64: ", err)
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
decryptedConfigs, err := crypto.DecryptAESEnv([]byte(b64DecryptedConfig))
|
decryptedConfigs, err := crypto.DecryptAESEnv([]byte(b64DecryptedConfig))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Error while decrypting env data from AES: ", err)
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = json.Unmarshal(decryptedConfigs, &result)
|
err = json.Unmarshal(decryptedConfigs, &result)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Error while unmarshalling env data: ", err)
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,6 +69,7 @@ func PersistEnv() error {
|
|||||||
|
|
||||||
encryptedConfig, err := crypto.EncryptEnvData(envstore.EnvStoreObj.GetEnvStoreClone())
|
encryptedConfig, err := crypto.EncryptEnvData(envstore.EnvStoreObj.GetEnvStoreClone())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Error while encrypting env data: ", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,6 +80,7 @@ func PersistEnv() error {
|
|||||||
|
|
||||||
env, err = db.Provider.AddEnv(env)
|
env, err = db.Provider.AddEnv(env)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Error while persisting env data to db: ", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -82,6 +89,7 @@ func PersistEnv() error {
|
|||||||
encryptionKey := env.Hash
|
encryptionKey := env.Hash
|
||||||
decryptedEncryptionKey, err := crypto.DecryptB64(encryptionKey)
|
decryptedEncryptionKey, err := crypto.DecryptB64(encryptionKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Error while decrypting encryption key: ", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,11 +97,13 @@ func PersistEnv() error {
|
|||||||
|
|
||||||
b64DecryptedConfig, err := crypto.DecryptB64(env.EnvData)
|
b64DecryptedConfig, err := crypto.DecryptB64(env.EnvData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Error while decrypting env data from B64: ", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
decryptedConfigs, err := crypto.DecryptAESEnv([]byte(b64DecryptedConfig))
|
decryptedConfigs, err := crypto.DecryptAESEnv([]byte(b64DecryptedConfig))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Error while decrypting env data from AES: ", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,6 +112,7 @@ func PersistEnv() error {
|
|||||||
|
|
||||||
err = json.Unmarshal(decryptedConfigs, &storeData)
|
err = json.Unmarshal(decryptedConfigs, &storeData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Error while unmarshalling env data: ", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,6 +180,7 @@ func PersistEnv() error {
|
|||||||
envstore.EnvStoreObj.UpdateEnvStore(storeData)
|
envstore.EnvStoreObj.UpdateEnvStore(storeData)
|
||||||
jwk, err := crypto.GenerateJWKBasedOnEnv()
|
jwk, err := crypto.GenerateJWKBasedOnEnv()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Error while generating JWK: ", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// updating jwk
|
// updating jwk
|
||||||
@@ -177,13 +189,14 @@ func PersistEnv() error {
|
|||||||
if hasChanged {
|
if hasChanged {
|
||||||
encryptedConfig, err := crypto.EncryptEnvData(storeData)
|
encryptedConfig, err := crypto.EncryptEnvData(storeData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Error while encrypting env data: ", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
env.EnvData = encryptedConfig
|
env.EnvData = encryptedConfig
|
||||||
_, err = db.Provider.UpdateEnv(env)
|
_, err = db.Provider.UpdateEnv(env)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error updating config:", err)
|
log.Debug("Failed to Update Config: ", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -13,6 +13,8 @@ var (
|
|||||||
ARG_DB_TYPE *string
|
ARG_DB_TYPE *string
|
||||||
// ARG_ENV_FILE is the cli arg variable for the env file
|
// ARG_ENV_FILE is the cli arg variable for the env file
|
||||||
ARG_ENV_FILE *string
|
ARG_ENV_FILE *string
|
||||||
|
// ARG_LOG_LEVEL is the cli arg variable for the log level
|
||||||
|
ARG_LOG_LEVEL *string
|
||||||
)
|
)
|
||||||
|
|
||||||
// Store data structure
|
// Store data structure
|
||||||
|
@@ -9,6 +9,7 @@ require (
|
|||||||
github.com/gin-gonic/gin v1.7.2
|
github.com/gin-gonic/gin v1.7.2
|
||||||
github.com/go-playground/validator/v10 v10.8.0 // indirect
|
github.com/go-playground/validator/v10 v10.8.0 // indirect
|
||||||
github.com/go-redis/redis/v8 v8.11.0
|
github.com/go-redis/redis/v8 v8.11.0
|
||||||
|
github.com/gocql/gocql v1.0.0
|
||||||
github.com/golang-jwt/jwt v3.2.2+incompatible
|
github.com/golang-jwt/jwt v3.2.2+incompatible
|
||||||
github.com/golang/protobuf v1.5.2 // indirect
|
github.com/golang/protobuf v1.5.2 // indirect
|
||||||
github.com/google/uuid v1.3.0
|
github.com/google/uuid v1.3.0
|
||||||
@@ -19,6 +20,7 @@ require (
|
|||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.1 // indirect
|
github.com/modern-go/reflect2 v1.0.1 // indirect
|
||||||
github.com/robertkrimen/otto v0.0.0-20211024170158-b87d35c0b86f
|
github.com/robertkrimen/otto v0.0.0-20211024170158-b87d35c0b86f
|
||||||
|
github.com/sirupsen/logrus v1.8.1 // indirect
|
||||||
github.com/stretchr/testify v1.7.0
|
github.com/stretchr/testify v1.7.0
|
||||||
github.com/ugorji/go v1.2.6 // indirect
|
github.com/ugorji/go v1.2.6 // indirect
|
||||||
github.com/vektah/gqlparser/v2 v2.2.0
|
github.com/vektah/gqlparser/v2 v2.2.0
|
||||||
|
@@ -48,6 +48,10 @@ github.com/arangodb/go-velocypack v0.0.0-20200318135517-5af53c29c67e h1:Xg+hGrY2
|
|||||||
github.com/arangodb/go-velocypack v0.0.0-20200318135517-5af53c29c67e/go.mod h1:mq7Shfa/CaixoDxiyAAc5jZ6CVBAyPaNQCGS7mkj4Ho=
|
github.com/arangodb/go-velocypack v0.0.0-20200318135517-5af53c29c67e/go.mod h1:mq7Shfa/CaixoDxiyAAc5jZ6CVBAyPaNQCGS7mkj4Ho=
|
||||||
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q=
|
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q=
|
||||||
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE=
|
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE=
|
||||||
|
github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932 h1:mXoPYz/Ul5HYEDvkta6I8/rnYM5gSdSV2tJ6XbZuEtY=
|
||||||
|
github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k=
|
||||||
|
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY=
|
||||||
|
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
|
||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
|
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
|
||||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
@@ -106,6 +110,8 @@ github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfC
|
|||||||
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||||
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
|
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
|
||||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
|
github.com/gocql/gocql v1.0.0 h1:UnbTERpP72VZ/viKE1Q1gPtmLvyTZTvuAstvSRydw/c=
|
||||||
|
github.com/gocql/gocql v1.0.0/go.mod h1:3gM2c4D3AnkISwBxGnMMsS8Oy4y2lhbPRsH4xnJrHG8=
|
||||||
github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw=
|
github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw=
|
||||||
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||||
@@ -140,8 +146,9 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw
|
|||||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||||
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
|
|
||||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
|
github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA=
|
||||||
|
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
@@ -175,6 +182,8 @@ github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f/go.mod h1:kBGZzfjB
|
|||||||
github.com/gorilla/mux v1.6.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
github.com/gorilla/mux v1.6.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
||||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
|
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8=
|
||||||
|
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4=
|
||||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
|
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
|
||||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
@@ -322,6 +331,8 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV
|
|||||||
github.com/shurcooL/vfsgen v0.0.0-20180121065927-ffb13db8def0/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw=
|
github.com/shurcooL/vfsgen v0.0.0-20180121065927-ffb13db8def0/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw=
|
||||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||||
|
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
|
||||||
|
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||||
@@ -677,6 +688,8 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8
|
|||||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||||
gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
|
gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
|
||||||
|
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
|
||||||
|
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||||
gopkg.in/mail.v2 v2.3.1 h1:WYFn/oANrAGP2C0dcV6/pbkPzv8yGzqTjPmTeO7qoXk=
|
gopkg.in/mail.v2 v2.3.1 h1:WYFn/oANrAGP2C0dcV6/pbkPzv8yGzqTjPmTeO7qoXk=
|
||||||
gopkg.in/mail.v2 v2.3.1/go.mod h1:htwXN1Qh09vZJ1NVKxQqHPBaCBbzKhp5GzuJEA4VJWw=
|
gopkg.in/mail.v2 v2.3.1/go.mod h1:htwXN1Qh09vZJ1NVKxQqHPBaCBbzKhp5GzuJEA4VJWw=
|
||||||
gopkg.in/readline.v1 v1.0.0-20160726135117-62c6fe619375/go.mod h1:lNEQeAhU009zbRxng+XOj5ITVgY24WcbNnQopyfKoYQ=
|
gopkg.in/readline.v1 v1.0.0-20160726135117-62c6fe619375/go.mod h1:lNEQeAhU009zbRxng+XOj5ITVgY24WcbNnQopyfKoYQ=
|
||||||
|
@@ -61,9 +61,13 @@ type ComplexityRoot struct {
|
|||||||
ClientSecret func(childComplexity int) int
|
ClientSecret func(childComplexity int) int
|
||||||
CookieName func(childComplexity int) int
|
CookieName func(childComplexity int) int
|
||||||
CustomAccessTokenScript func(childComplexity int) int
|
CustomAccessTokenScript func(childComplexity int) int
|
||||||
|
DatabaseHost func(childComplexity int) int
|
||||||
DatabaseName func(childComplexity int) int
|
DatabaseName func(childComplexity int) int
|
||||||
|
DatabasePassword func(childComplexity int) int
|
||||||
|
DatabasePort func(childComplexity int) int
|
||||||
DatabaseType func(childComplexity int) int
|
DatabaseType func(childComplexity int) int
|
||||||
DatabaseURL func(childComplexity int) int
|
DatabaseURL func(childComplexity int) int
|
||||||
|
DatabaseUsername func(childComplexity int) int
|
||||||
DefaultRoles func(childComplexity int) int
|
DefaultRoles func(childComplexity int) int
|
||||||
DisableBasicAuthentication func(childComplexity int) int
|
DisableBasicAuthentication func(childComplexity int) int
|
||||||
DisableEmailVerification func(childComplexity int) int
|
DisableEmailVerification func(childComplexity int) int
|
||||||
@@ -356,6 +360,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
|||||||
|
|
||||||
return e.complexity.Env.CustomAccessTokenScript(childComplexity), true
|
return e.complexity.Env.CustomAccessTokenScript(childComplexity), true
|
||||||
|
|
||||||
|
case "Env.DATABASE_HOST":
|
||||||
|
if e.complexity.Env.DatabaseHost == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return e.complexity.Env.DatabaseHost(childComplexity), true
|
||||||
|
|
||||||
case "Env.DATABASE_NAME":
|
case "Env.DATABASE_NAME":
|
||||||
if e.complexity.Env.DatabaseName == nil {
|
if e.complexity.Env.DatabaseName == nil {
|
||||||
break
|
break
|
||||||
@@ -363,6 +374,20 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
|||||||
|
|
||||||
return e.complexity.Env.DatabaseName(childComplexity), true
|
return e.complexity.Env.DatabaseName(childComplexity), true
|
||||||
|
|
||||||
|
case "Env.DATABASE_PASSWORD":
|
||||||
|
if e.complexity.Env.DatabasePassword == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return e.complexity.Env.DatabasePassword(childComplexity), true
|
||||||
|
|
||||||
|
case "Env.DATABASE_PORT":
|
||||||
|
if e.complexity.Env.DatabasePort == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return e.complexity.Env.DatabasePort(childComplexity), true
|
||||||
|
|
||||||
case "Env.DATABASE_TYPE":
|
case "Env.DATABASE_TYPE":
|
||||||
if e.complexity.Env.DatabaseType == nil {
|
if e.complexity.Env.DatabaseType == nil {
|
||||||
break
|
break
|
||||||
@@ -377,6 +402,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
|||||||
|
|
||||||
return e.complexity.Env.DatabaseURL(childComplexity), true
|
return e.complexity.Env.DatabaseURL(childComplexity), true
|
||||||
|
|
||||||
|
case "Env.DATABASE_USERNAME":
|
||||||
|
if e.complexity.Env.DatabaseUsername == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return e.complexity.Env.DatabaseUsername(childComplexity), true
|
||||||
|
|
||||||
case "Env.DEFAULT_ROLES":
|
case "Env.DEFAULT_ROLES":
|
||||||
if e.complexity.Env.DefaultRoles == nil {
|
if e.complexity.Env.DefaultRoles == nil {
|
||||||
break
|
break
|
||||||
@@ -1394,6 +1426,10 @@ type Env {
|
|||||||
DATABASE_NAME: String!
|
DATABASE_NAME: String!
|
||||||
DATABASE_URL: String!
|
DATABASE_URL: String!
|
||||||
DATABASE_TYPE: String!
|
DATABASE_TYPE: String!
|
||||||
|
DATABASE_USERNAME: String!
|
||||||
|
DATABASE_PASSWORD: String!
|
||||||
|
DATABASE_HOST: String!
|
||||||
|
DATABASE_PORT: String!
|
||||||
CLIENT_ID: String!
|
CLIENT_ID: String!
|
||||||
CLIENT_SECRET: String!
|
CLIENT_SECRET: String!
|
||||||
CUSTOM_ACCESS_TOKEN_SCRIPT: String
|
CUSTOM_ACCESS_TOKEN_SCRIPT: String
|
||||||
@@ -2400,6 +2436,146 @@ func (ec *executionContext) _Env_DATABASE_TYPE(ctx context.Context, field graphq
|
|||||||
return ec.marshalNString2string(ctx, field.Selections, res)
|
return ec.marshalNString2string(ctx, field.Selections, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) _Env_DATABASE_USERNAME(ctx context.Context, field graphql.CollectedField, obj *model.Env) (ret graphql.Marshaler) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
ec.Error(ctx, ec.Recover(ctx, r))
|
||||||
|
ret = graphql.Null
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
fc := &graphql.FieldContext{
|
||||||
|
Object: "Env",
|
||||||
|
Field: field,
|
||||||
|
Args: nil,
|
||||||
|
IsMethod: false,
|
||||||
|
IsResolver: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = graphql.WithFieldContext(ctx, fc)
|
||||||
|
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||||
|
ctx = rctx // use context from middleware stack in children
|
||||||
|
return obj.DatabaseUsername, nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
ec.Error(ctx, err)
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
if resTmp == nil {
|
||||||
|
if !graphql.HasFieldError(ctx, fc) {
|
||||||
|
ec.Errorf(ctx, "must not be null")
|
||||||
|
}
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
res := resTmp.(string)
|
||||||
|
fc.Result = res
|
||||||
|
return ec.marshalNString2string(ctx, field.Selections, res)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) _Env_DATABASE_PASSWORD(ctx context.Context, field graphql.CollectedField, obj *model.Env) (ret graphql.Marshaler) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
ec.Error(ctx, ec.Recover(ctx, r))
|
||||||
|
ret = graphql.Null
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
fc := &graphql.FieldContext{
|
||||||
|
Object: "Env",
|
||||||
|
Field: field,
|
||||||
|
Args: nil,
|
||||||
|
IsMethod: false,
|
||||||
|
IsResolver: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = graphql.WithFieldContext(ctx, fc)
|
||||||
|
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||||
|
ctx = rctx // use context from middleware stack in children
|
||||||
|
return obj.DatabasePassword, nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
ec.Error(ctx, err)
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
if resTmp == nil {
|
||||||
|
if !graphql.HasFieldError(ctx, fc) {
|
||||||
|
ec.Errorf(ctx, "must not be null")
|
||||||
|
}
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
res := resTmp.(string)
|
||||||
|
fc.Result = res
|
||||||
|
return ec.marshalNString2string(ctx, field.Selections, res)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) _Env_DATABASE_HOST(ctx context.Context, field graphql.CollectedField, obj *model.Env) (ret graphql.Marshaler) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
ec.Error(ctx, ec.Recover(ctx, r))
|
||||||
|
ret = graphql.Null
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
fc := &graphql.FieldContext{
|
||||||
|
Object: "Env",
|
||||||
|
Field: field,
|
||||||
|
Args: nil,
|
||||||
|
IsMethod: false,
|
||||||
|
IsResolver: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = graphql.WithFieldContext(ctx, fc)
|
||||||
|
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||||
|
ctx = rctx // use context from middleware stack in children
|
||||||
|
return obj.DatabaseHost, nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
ec.Error(ctx, err)
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
if resTmp == nil {
|
||||||
|
if !graphql.HasFieldError(ctx, fc) {
|
||||||
|
ec.Errorf(ctx, "must not be null")
|
||||||
|
}
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
res := resTmp.(string)
|
||||||
|
fc.Result = res
|
||||||
|
return ec.marshalNString2string(ctx, field.Selections, res)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) _Env_DATABASE_PORT(ctx context.Context, field graphql.CollectedField, obj *model.Env) (ret graphql.Marshaler) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
ec.Error(ctx, ec.Recover(ctx, r))
|
||||||
|
ret = graphql.Null
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
fc := &graphql.FieldContext{
|
||||||
|
Object: "Env",
|
||||||
|
Field: field,
|
||||||
|
Args: nil,
|
||||||
|
IsMethod: false,
|
||||||
|
IsResolver: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = graphql.WithFieldContext(ctx, fc)
|
||||||
|
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||||
|
ctx = rctx // use context from middleware stack in children
|
||||||
|
return obj.DatabasePort, nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
ec.Error(ctx, err)
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
if resTmp == nil {
|
||||||
|
if !graphql.HasFieldError(ctx, fc) {
|
||||||
|
ec.Errorf(ctx, "must not be null")
|
||||||
|
}
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
res := resTmp.(string)
|
||||||
|
fc.Result = res
|
||||||
|
return ec.marshalNString2string(ctx, field.Selections, res)
|
||||||
|
}
|
||||||
|
|
||||||
func (ec *executionContext) _Env_CLIENT_ID(ctx context.Context, field graphql.CollectedField, obj *model.Env) (ret graphql.Marshaler) {
|
func (ec *executionContext) _Env_CLIENT_ID(ctx context.Context, field graphql.CollectedField, obj *model.Env) (ret graphql.Marshaler) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
@@ -8780,6 +8956,26 @@ func (ec *executionContext) _Env(ctx context.Context, sel ast.SelectionSet, obj
|
|||||||
if out.Values[i] == graphql.Null {
|
if out.Values[i] == graphql.Null {
|
||||||
invalids++
|
invalids++
|
||||||
}
|
}
|
||||||
|
case "DATABASE_USERNAME":
|
||||||
|
out.Values[i] = ec._Env_DATABASE_USERNAME(ctx, field, obj)
|
||||||
|
if out.Values[i] == graphql.Null {
|
||||||
|
invalids++
|
||||||
|
}
|
||||||
|
case "DATABASE_PASSWORD":
|
||||||
|
out.Values[i] = ec._Env_DATABASE_PASSWORD(ctx, field, obj)
|
||||||
|
if out.Values[i] == graphql.Null {
|
||||||
|
invalids++
|
||||||
|
}
|
||||||
|
case "DATABASE_HOST":
|
||||||
|
out.Values[i] = ec._Env_DATABASE_HOST(ctx, field, obj)
|
||||||
|
if out.Values[i] == graphql.Null {
|
||||||
|
invalids++
|
||||||
|
}
|
||||||
|
case "DATABASE_PORT":
|
||||||
|
out.Values[i] = ec._Env_DATABASE_PORT(ctx, field, obj)
|
||||||
|
if out.Values[i] == graphql.Null {
|
||||||
|
invalids++
|
||||||
|
}
|
||||||
case "CLIENT_ID":
|
case "CLIENT_ID":
|
||||||
out.Values[i] = ec._Env_CLIENT_ID(ctx, field, obj)
|
out.Values[i] = ec._Env_CLIENT_ID(ctx, field, obj)
|
||||||
if out.Values[i] == graphql.Null {
|
if out.Values[i] == graphql.Null {
|
||||||
|
@@ -29,6 +29,10 @@ type Env struct {
|
|||||||
DatabaseName string `json:"DATABASE_NAME"`
|
DatabaseName string `json:"DATABASE_NAME"`
|
||||||
DatabaseURL string `json:"DATABASE_URL"`
|
DatabaseURL string `json:"DATABASE_URL"`
|
||||||
DatabaseType string `json:"DATABASE_TYPE"`
|
DatabaseType string `json:"DATABASE_TYPE"`
|
||||||
|
DatabaseUsername string `json:"DATABASE_USERNAME"`
|
||||||
|
DatabasePassword string `json:"DATABASE_PASSWORD"`
|
||||||
|
DatabaseHost string `json:"DATABASE_HOST"`
|
||||||
|
DatabasePort string `json:"DATABASE_PORT"`
|
||||||
ClientID string `json:"CLIENT_ID"`
|
ClientID string `json:"CLIENT_ID"`
|
||||||
ClientSecret string `json:"CLIENT_SECRET"`
|
ClientSecret string `json:"CLIENT_SECRET"`
|
||||||
CustomAccessTokenScript *string `json:"CUSTOM_ACCESS_TOKEN_SCRIPT"`
|
CustomAccessTokenScript *string `json:"CUSTOM_ACCESS_TOKEN_SCRIPT"`
|
||||||
|
@@ -92,6 +92,10 @@ type Env {
|
|||||||
DATABASE_NAME: String!
|
DATABASE_NAME: String!
|
||||||
DATABASE_URL: String!
|
DATABASE_URL: String!
|
||||||
DATABASE_TYPE: String!
|
DATABASE_TYPE: String!
|
||||||
|
DATABASE_USERNAME: String!
|
||||||
|
DATABASE_PASSWORD: String!
|
||||||
|
DATABASE_HOST: String!
|
||||||
|
DATABASE_PORT: String!
|
||||||
CLIENT_ID: String!
|
CLIENT_ID: String!
|
||||||
CLIENT_SECRET: String!
|
CLIENT_SECRET: String!
|
||||||
CUSTOM_ACCESS_TOKEN_SCRIPT: String
|
CUSTOM_ACCESS_TOKEN_SCRIPT: String
|
||||||
|
@@ -1,14 +1,15 @@
|
|||||||
package handlers
|
package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
"github.com/authorizerdev/authorizer/server/envstore"
|
||||||
"github.com/authorizerdev/authorizer/server/utils"
|
"github.com/authorizerdev/authorizer/server/utils"
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// State is the struct that holds authorizer url and redirect url
|
// State is the struct that holds authorizer url and redirect url
|
||||||
@@ -23,6 +24,7 @@ func AppHandler() gin.HandlerFunc {
|
|||||||
return func(c *gin.Context) {
|
return func(c *gin.Context) {
|
||||||
hostname := utils.GetHost(c)
|
hostname := utils.GetHost(c)
|
||||||
if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableLoginPage) {
|
if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableLoginPage) {
|
||||||
|
log.Debug("Login page is disabled")
|
||||||
c.JSON(400, gin.H{"error": "login page is not enabled"})
|
c.JSON(400, gin.H{"error": "login page is not enabled"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -43,6 +45,7 @@ func AppHandler() gin.HandlerFunc {
|
|||||||
} else {
|
} else {
|
||||||
// validate redirect url with allowed origins
|
// validate redirect url with allowed origins
|
||||||
if !utils.IsValidOrigin(redirect_uri) {
|
if !utils.IsValidOrigin(redirect_uri) {
|
||||||
|
log.Debug("Invalid redirect_uri")
|
||||||
c.JSON(400, gin.H{"error": "invalid redirect url"})
|
c.JSON(400, gin.H{"error": "invalid redirect url"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -52,7 +55,7 @@ func AppHandler() gin.HandlerFunc {
|
|||||||
if pusher := c.Writer.Pusher(); pusher != nil {
|
if pusher := c.Writer.Pusher(); pusher != nil {
|
||||||
// use pusher.Push() to do server push
|
// use pusher.Push() to do server push
|
||||||
if err := pusher.Push("/app/build/bundle.js", nil); err != nil {
|
if err := pusher.Push("/app/build/bundle.js", nil); err != nil {
|
||||||
log.Printf("Failed to push: %v", err)
|
log.Debug("Failed to push file path: ", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c.HTML(http.StatusOK, "app.tmpl", gin.H{
|
c.HTML(http.StatusOK, "app.tmpl", gin.H{
|
||||||
|
@@ -6,14 +6,16 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/cookie"
|
"github.com/authorizerdev/authorizer/server/cookie"
|
||||||
"github.com/authorizerdev/authorizer/server/db"
|
"github.com/authorizerdev/authorizer/server/db"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
"github.com/authorizerdev/authorizer/server/envstore"
|
||||||
"github.com/authorizerdev/authorizer/server/sessionstore"
|
"github.com/authorizerdev/authorizer/server/sessionstore"
|
||||||
"github.com/authorizerdev/authorizer/server/token"
|
"github.com/authorizerdev/authorizer/server/token"
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/google/uuid"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// AuthorizeHandler is the handler for the /authorize route
|
// AuthorizeHandler is the handler for the /authorize route
|
||||||
@@ -48,6 +50,7 @@ func AuthorizeHandler() gin.HandlerFunc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if responseMode != "query" && responseMode != "web_message" {
|
if responseMode != "query" && responseMode != "web_message" {
|
||||||
|
log.Debug("Invalid response_mode: ", responseMode)
|
||||||
gc.JSON(400, gin.H{"error": "invalid response mode"})
|
gc.JSON(400, gin.H{"error": "invalid response mode"})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,6 +66,7 @@ func AuthorizeHandler() gin.HandlerFunc {
|
|||||||
if isQuery {
|
if isQuery {
|
||||||
gc.Redirect(http.StatusFound, loginURL)
|
gc.Redirect(http.StatusFound, loginURL)
|
||||||
} else {
|
} else {
|
||||||
|
log.Debug("Failed to get client_id: ", clientID)
|
||||||
gc.HTML(http.StatusOK, template, gin.H{
|
gc.HTML(http.StatusOK, template, gin.H{
|
||||||
"target_origin": redirectURI,
|
"target_origin": redirectURI,
|
||||||
"authorization_response": map[string]interface{}{
|
"authorization_response": map[string]interface{}{
|
||||||
@@ -80,6 +84,7 @@ func AuthorizeHandler() gin.HandlerFunc {
|
|||||||
if isQuery {
|
if isQuery {
|
||||||
gc.Redirect(http.StatusFound, loginURL)
|
gc.Redirect(http.StatusFound, loginURL)
|
||||||
} else {
|
} else {
|
||||||
|
log.Debug("Invalid client_id: ", clientID)
|
||||||
gc.HTML(http.StatusOK, template, gin.H{
|
gc.HTML(http.StatusOK, template, gin.H{
|
||||||
"target_origin": redirectURI,
|
"target_origin": redirectURI,
|
||||||
"authorization_response": map[string]interface{}{
|
"authorization_response": map[string]interface{}{
|
||||||
@@ -97,6 +102,7 @@ func AuthorizeHandler() gin.HandlerFunc {
|
|||||||
if isQuery {
|
if isQuery {
|
||||||
gc.Redirect(http.StatusFound, loginURL)
|
gc.Redirect(http.StatusFound, loginURL)
|
||||||
} else {
|
} else {
|
||||||
|
log.Debug("Failed to get state: ", state)
|
||||||
gc.HTML(http.StatusOK, template, gin.H{
|
gc.HTML(http.StatusOK, template, gin.H{
|
||||||
"target_origin": redirectURI,
|
"target_origin": redirectURI,
|
||||||
"authorization_response": map[string]interface{}{
|
"authorization_response": map[string]interface{}{
|
||||||
@@ -121,6 +127,7 @@ func AuthorizeHandler() gin.HandlerFunc {
|
|||||||
if isQuery {
|
if isQuery {
|
||||||
gc.Redirect(http.StatusFound, loginURL)
|
gc.Redirect(http.StatusFound, loginURL)
|
||||||
} else {
|
} else {
|
||||||
|
log.Debug("Invalid response_type: ", responseType)
|
||||||
gc.HTML(http.StatusOK, template, gin.H{
|
gc.HTML(http.StatusOK, template, gin.H{
|
||||||
"target_origin": redirectURI,
|
"target_origin": redirectURI,
|
||||||
"authorization_response": map[string]interface{}{
|
"authorization_response": map[string]interface{}{
|
||||||
@@ -139,6 +146,7 @@ func AuthorizeHandler() gin.HandlerFunc {
|
|||||||
if isQuery {
|
if isQuery {
|
||||||
gc.Redirect(http.StatusFound, loginURL)
|
gc.Redirect(http.StatusFound, loginURL)
|
||||||
} else {
|
} else {
|
||||||
|
log.Debug("Failed to get code_challenge: ", codeChallenge)
|
||||||
gc.HTML(http.StatusBadRequest, template, gin.H{
|
gc.HTML(http.StatusBadRequest, template, gin.H{
|
||||||
"target_origin": redirectURI,
|
"target_origin": redirectURI,
|
||||||
"authorization_response": map[string]interface{}{
|
"authorization_response": map[string]interface{}{
|
||||||
|
@@ -3,9 +3,11 @@ package handlers
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
"github.com/authorizerdev/authorizer/server/envstore"
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func JWKsHandler() gin.HandlerFunc {
|
func JWKsHandler() gin.HandlerFunc {
|
||||||
@@ -14,6 +16,7 @@ func JWKsHandler() gin.HandlerFunc {
|
|||||||
jwk := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJWK)
|
jwk := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyJWK)
|
||||||
err := json.Unmarshal([]byte(jwk), &data)
|
err := json.Unmarshal([]byte(jwk), &data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to parse JWK: ", err)
|
||||||
c.JSON(500, gin.H{
|
c.JSON(500, gin.H{
|
||||||
"error": err.Error(),
|
"error": err.Error(),
|
||||||
})
|
})
|
||||||
|
@@ -4,10 +4,12 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/cookie"
|
"github.com/authorizerdev/authorizer/server/cookie"
|
||||||
"github.com/authorizerdev/authorizer/server/crypto"
|
"github.com/authorizerdev/authorizer/server/crypto"
|
||||||
"github.com/authorizerdev/authorizer/server/sessionstore"
|
"github.com/authorizerdev/authorizer/server/sessionstore"
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Handler to logout user
|
// Handler to logout user
|
||||||
@@ -17,6 +19,7 @@ func LogoutHandler() gin.HandlerFunc {
|
|||||||
// get fingerprint hash
|
// get fingerprint hash
|
||||||
fingerprintHash, err := cookie.GetSession(gc)
|
fingerprintHash, err := cookie.GetSession(gc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to get session: ", err)
|
||||||
gc.JSON(http.StatusUnauthorized, gin.H{
|
gc.JSON(http.StatusUnauthorized, gin.H{
|
||||||
"error": err.Error(),
|
"error": err.Error(),
|
||||||
})
|
})
|
||||||
@@ -25,6 +28,7 @@ func LogoutHandler() gin.HandlerFunc {
|
|||||||
|
|
||||||
decryptedFingerPrint, err := crypto.DecryptAES(fingerprintHash)
|
decryptedFingerPrint, err := crypto.DecryptAES(fingerprintHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to decrypt fingerprint: ", err)
|
||||||
gc.JSON(http.StatusUnauthorized, gin.H{
|
gc.JSON(http.StatusUnauthorized, gin.H{
|
||||||
"error": err.Error(),
|
"error": err.Error(),
|
||||||
})
|
})
|
||||||
|
@@ -5,12 +5,16 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/coreos/go-oidc/v3/oidc"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"golang.org/x/oauth2"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/cookie"
|
"github.com/authorizerdev/authorizer/server/cookie"
|
||||||
"github.com/authorizerdev/authorizer/server/db"
|
"github.com/authorizerdev/authorizer/server/db"
|
||||||
@@ -20,9 +24,6 @@ import (
|
|||||||
"github.com/authorizerdev/authorizer/server/sessionstore"
|
"github.com/authorizerdev/authorizer/server/sessionstore"
|
||||||
"github.com/authorizerdev/authorizer/server/token"
|
"github.com/authorizerdev/authorizer/server/token"
|
||||||
"github.com/authorizerdev/authorizer/server/utils"
|
"github.com/authorizerdev/authorizer/server/utils"
|
||||||
"github.com/coreos/go-oidc/v3/oidc"
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"golang.org/x/oauth2"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// OAuthCallbackHandler handles the OAuth callback for various oauth providers
|
// OAuthCallbackHandler handles the OAuth callback for various oauth providers
|
||||||
@@ -33,6 +34,7 @@ func OAuthCallbackHandler() gin.HandlerFunc {
|
|||||||
|
|
||||||
sessionState := sessionstore.GetState(state)
|
sessionState := sessionstore.GetState(state)
|
||||||
if sessionState == "" {
|
if sessionState == "" {
|
||||||
|
log.Debug("Invalid oauth state: ", state)
|
||||||
c.JSON(400, gin.H{"error": "invalid oauth state"})
|
c.JSON(400, gin.H{"error": "invalid oauth state"})
|
||||||
}
|
}
|
||||||
sessionstore.GetState(state)
|
sessionstore.GetState(state)
|
||||||
@@ -40,6 +42,7 @@ func OAuthCallbackHandler() gin.HandlerFunc {
|
|||||||
sessionSplit := strings.Split(state, "___")
|
sessionSplit := strings.Split(state, "___")
|
||||||
|
|
||||||
if len(sessionSplit) < 3 {
|
if len(sessionSplit) < 3 {
|
||||||
|
log.Debug("Unable to get redirect url from state: ", state)
|
||||||
c.JSON(400, gin.H{"error": "invalid redirect url"})
|
c.JSON(400, gin.H{"error": "invalid redirect url"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -60,18 +63,22 @@ func OAuthCallbackHandler() gin.HandlerFunc {
|
|||||||
case constants.SignupMethodFacebook:
|
case constants.SignupMethodFacebook:
|
||||||
user, err = processFacebookUserInfo(code)
|
user, err = processFacebookUserInfo(code)
|
||||||
default:
|
default:
|
||||||
|
log.Info("Invalid oauth provider")
|
||||||
err = fmt.Errorf(`invalid oauth provider`)
|
err = fmt.Errorf(`invalid oauth provider`)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to process user info: ", err)
|
||||||
c.JSON(400, gin.H{"error": err.Error()})
|
c.JSON(400, gin.H{"error": err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
existingUser, err := db.Provider.GetUserByEmail(user.Email)
|
existingUser, err := db.Provider.GetUserByEmail(user.Email)
|
||||||
|
log := log.WithField("user", user.Email)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableSignUp) {
|
if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableSignUp) {
|
||||||
|
log.Debug("Failed to signup as disabled")
|
||||||
c.JSON(400, gin.H{"error": "signup is disabled for this instance"})
|
c.JSON(400, gin.H{"error": "signup is disabled for this instance"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -86,6 +93,7 @@ func OAuthCallbackHandler() gin.HandlerFunc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if hasProtectedRole {
|
if hasProtectedRole {
|
||||||
|
log.Debug("Signup is not allowed with protected roles:", inputRoles)
|
||||||
c.JSON(400, gin.H{"error": "invalid role"})
|
c.JSON(400, gin.H{"error": "invalid role"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -96,6 +104,7 @@ func OAuthCallbackHandler() gin.HandlerFunc {
|
|||||||
user, _ = db.Provider.AddUser(user)
|
user, _ = db.Provider.AddUser(user)
|
||||||
} else {
|
} else {
|
||||||
if user.RevokedTimestamp != nil {
|
if user.RevokedTimestamp != nil {
|
||||||
|
log.Debug("User access revoked at: ", user.RevokedTimestamp)
|
||||||
c.JSON(400, gin.H{"error": "user access has been revoked"})
|
c.JSON(400, gin.H{"error": "user access has been revoked"})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,6 +146,7 @@ func OAuthCallbackHandler() gin.HandlerFunc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if hasProtectedRole {
|
if hasProtectedRole {
|
||||||
|
log.Debug("Invalid role. User is using protected unassigned role")
|
||||||
c.JSON(400, gin.H{"error": "invalid role"})
|
c.JSON(400, gin.H{"error": "invalid role"})
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
@@ -148,6 +158,7 @@ func OAuthCallbackHandler() gin.HandlerFunc {
|
|||||||
|
|
||||||
user, err = db.Provider.UpdateUser(user)
|
user, err = db.Provider.UpdateUser(user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to update user: ", err)
|
||||||
c.JSON(500, gin.H{"error": err.Error()})
|
c.JSON(500, gin.H{"error": err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -155,6 +166,7 @@ func OAuthCallbackHandler() gin.HandlerFunc {
|
|||||||
|
|
||||||
authToken, err := token.CreateAuthToken(c, user, inputRoles, scopes)
|
authToken, err := token.CreateAuthToken(c, user, inputRoles, scopes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to create auth token: ", err)
|
||||||
c.JSON(500, gin.H{"error": err.Error()})
|
c.JSON(500, gin.H{"error": err.Error()})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,7 +186,11 @@ func OAuthCallbackHandler() gin.HandlerFunc {
|
|||||||
sessionstore.SetState(authToken.RefreshToken.Token, authToken.FingerPrint+"@"+user.ID)
|
sessionstore.SetState(authToken.RefreshToken.Token, authToken.FingerPrint+"@"+user.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
go utils.SaveSessionInDB(c, user.ID)
|
go db.Provider.AddSession(models.Session{
|
||||||
|
UserID: user.ID,
|
||||||
|
UserAgent: utils.GetUserAgent(c.Request),
|
||||||
|
IP: utils.GetIP(c.Request),
|
||||||
|
})
|
||||||
if strings.Contains(redirectURL, "?") {
|
if strings.Contains(redirectURL, "?") {
|
||||||
redirectURL = redirectURL + "&" + params
|
redirectURL = redirectURL + "&" + params
|
||||||
} else {
|
} else {
|
||||||
@@ -190,6 +206,7 @@ func processGoogleUserInfo(code string) (models.User, error) {
|
|||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
oauth2Token, err := oauth.OAuthProviders.GoogleConfig.Exchange(ctx, code)
|
oauth2Token, err := oauth.OAuthProviders.GoogleConfig.Exchange(ctx, code)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to exchange code for token: ", err)
|
||||||
return user, fmt.Errorf("invalid google exchange code: %s", err.Error())
|
return user, fmt.Errorf("invalid google exchange code: %s", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,16 +215,19 @@ func processGoogleUserInfo(code string) (models.User, error) {
|
|||||||
// Extract the ID Token from OAuth2 token.
|
// Extract the ID Token from OAuth2 token.
|
||||||
rawIDToken, ok := oauth2Token.Extra("id_token").(string)
|
rawIDToken, ok := oauth2Token.Extra("id_token").(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
log.Debug("Failed to extract ID Token from OAuth2 token")
|
||||||
return user, fmt.Errorf("unable to extract id_token")
|
return user, fmt.Errorf("unable to extract id_token")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse and verify ID Token payload.
|
// Parse and verify ID Token payload.
|
||||||
idToken, err := verifier.Verify(ctx, rawIDToken)
|
idToken, err := verifier.Verify(ctx, rawIDToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to verify ID Token: ", err)
|
||||||
return user, fmt.Errorf("unable to verify id_token: %s", err.Error())
|
return user, fmt.Errorf("unable to verify id_token: %s", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := idToken.Claims(&user); err != nil {
|
if err := idToken.Claims(&user); err != nil {
|
||||||
|
log.Debug("Failed to parse ID Token claims: ", err)
|
||||||
return user, fmt.Errorf("unable to extract claims")
|
return user, fmt.Errorf("unable to extract claims")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,11 +238,13 @@ func processGithubUserInfo(code string) (models.User, error) {
|
|||||||
user := models.User{}
|
user := models.User{}
|
||||||
token, err := oauth.OAuthProviders.GithubConfig.Exchange(oauth2.NoContext, code)
|
token, err := oauth.OAuthProviders.GithubConfig.Exchange(oauth2.NoContext, code)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to exchange code for token: ", err)
|
||||||
return user, fmt.Errorf("invalid github exchange code: %s", err.Error())
|
return user, fmt.Errorf("invalid github exchange code: %s", err.Error())
|
||||||
}
|
}
|
||||||
client := http.Client{}
|
client := http.Client{}
|
||||||
req, err := http.NewRequest("GET", constants.GithubUserInfoURL, nil)
|
req, err := http.NewRequest("GET", constants.GithubUserInfoURL, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to create github user info request: ", err)
|
||||||
return user, fmt.Errorf("error creating github user info request: %s", err.Error())
|
return user, fmt.Errorf("error creating github user info request: %s", err.Error())
|
||||||
}
|
}
|
||||||
req.Header = http.Header{
|
req.Header = http.Header{
|
||||||
@@ -231,12 +253,14 @@ func processGithubUserInfo(code string) (models.User, error) {
|
|||||||
|
|
||||||
response, err := client.Do(req)
|
response, err := client.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to request github user info: ", err)
|
||||||
return user, err
|
return user, err
|
||||||
}
|
}
|
||||||
|
|
||||||
defer response.Body.Close()
|
defer response.Body.Close()
|
||||||
body, err := ioutil.ReadAll(response.Body)
|
body, err := ioutil.ReadAll(response.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to read github user info response body: ", err)
|
||||||
return user, fmt.Errorf("failed to read github response body: %s", err.Error())
|
return user, fmt.Errorf("failed to read github response body: %s", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,7 +283,7 @@ func processGithubUserInfo(code string) (models.User, error) {
|
|||||||
GivenName: &firstName,
|
GivenName: &firstName,
|
||||||
FamilyName: &lastName,
|
FamilyName: &lastName,
|
||||||
Picture: &picture,
|
Picture: &picture,
|
||||||
Email: userRawData["sub"],
|
Email: userRawData["email"],
|
||||||
}
|
}
|
||||||
|
|
||||||
return user, nil
|
return user, nil
|
||||||
@@ -269,23 +293,26 @@ func processFacebookUserInfo(code string) (models.User, error) {
|
|||||||
user := models.User{}
|
user := models.User{}
|
||||||
token, err := oauth.OAuthProviders.FacebookConfig.Exchange(oauth2.NoContext, code)
|
token, err := oauth.OAuthProviders.FacebookConfig.Exchange(oauth2.NoContext, code)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Invalid facebook exchange code: ", err)
|
||||||
return user, fmt.Errorf("invalid facebook exchange code: %s", err.Error())
|
return user, fmt.Errorf("invalid facebook exchange code: %s", err.Error())
|
||||||
}
|
}
|
||||||
client := http.Client{}
|
client := http.Client{}
|
||||||
req, err := http.NewRequest("GET", constants.FacebookUserInfoURL+token.AccessToken, nil)
|
req, err := http.NewRequest("GET", constants.FacebookUserInfoURL+token.AccessToken, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Error creating facebook user info request: ", err)
|
||||||
return user, fmt.Errorf("error creating facebook user info request: %s", err.Error())
|
return user, fmt.Errorf("error creating facebook user info request: %s", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
response, err := client.Do(req)
|
response, err := client.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error processing facebook user info:", err)
|
log.Debug("Failed to process facebook user: ", err)
|
||||||
return user, err
|
return user, err
|
||||||
}
|
}
|
||||||
|
|
||||||
defer response.Body.Close()
|
defer response.Body.Close()
|
||||||
body, err := ioutil.ReadAll(response.Body)
|
body, err := ioutil.ReadAll(response.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to read facebook response: ", err)
|
||||||
return user, fmt.Errorf("failed to read facebook response body: %s", err.Error())
|
return user, fmt.Errorf("failed to read facebook response body: %s", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -4,12 +4,14 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
"github.com/authorizerdev/authorizer/server/envstore"
|
||||||
"github.com/authorizerdev/authorizer/server/oauth"
|
"github.com/authorizerdev/authorizer/server/oauth"
|
||||||
"github.com/authorizerdev/authorizer/server/sessionstore"
|
"github.com/authorizerdev/authorizer/server/sessionstore"
|
||||||
"github.com/authorizerdev/authorizer/server/utils"
|
"github.com/authorizerdev/authorizer/server/utils"
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// OAuthLoginHandler set host in the oauth state that is useful for redirecting to oauth_callback
|
// OAuthLoginHandler set host in the oauth state that is useful for redirecting to oauth_callback
|
||||||
@@ -26,6 +28,7 @@ func OAuthLoginHandler() gin.HandlerFunc {
|
|||||||
scopeString := strings.TrimSpace(c.Query("scope"))
|
scopeString := strings.TrimSpace(c.Query("scope"))
|
||||||
|
|
||||||
if redirectURI == "" {
|
if redirectURI == "" {
|
||||||
|
log.Debug("redirect_uri is empty")
|
||||||
c.JSON(400, gin.H{
|
c.JSON(400, gin.H{
|
||||||
"error": "invalid redirect uri",
|
"error": "invalid redirect uri",
|
||||||
})
|
})
|
||||||
@@ -33,6 +36,7 @@ func OAuthLoginHandler() gin.HandlerFunc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if state == "" {
|
if state == "" {
|
||||||
|
log.Debug("state is empty")
|
||||||
c.JSON(400, gin.H{
|
c.JSON(400, gin.H{
|
||||||
"error": "invalid state",
|
"error": "invalid state",
|
||||||
})
|
})
|
||||||
@@ -52,7 +56,8 @@ func OAuthLoginHandler() gin.HandlerFunc {
|
|||||||
|
|
||||||
// use protected roles verification for admin login only.
|
// use protected roles verification for admin login only.
|
||||||
// though if not associated with user, it will be rejected from oauth_callback
|
// though if not associated with user, it will be rejected from oauth_callback
|
||||||
if !utils.IsValidRoles(append([]string{}, append(envstore.EnvStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyRoles), envstore.EnvStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyProtectedRoles)...)...), rolesSplit) {
|
if !utils.IsValidRoles(rolesSplit, append([]string{}, append(envstore.EnvStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyRoles), envstore.EnvStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyProtectedRoles)...)...)) {
|
||||||
|
log.Debug("Invalid roles: ", roles)
|
||||||
c.JSON(400, gin.H{
|
c.JSON(400, gin.H{
|
||||||
"error": "invalid role",
|
"error": "invalid role",
|
||||||
})
|
})
|
||||||
@@ -69,6 +74,7 @@ func OAuthLoginHandler() gin.HandlerFunc {
|
|||||||
switch provider {
|
switch provider {
|
||||||
case constants.SignupMethodGoogle:
|
case constants.SignupMethodGoogle:
|
||||||
if oauth.OAuthProviders.GoogleConfig == nil {
|
if oauth.OAuthProviders.GoogleConfig == nil {
|
||||||
|
log.Debug("Google OAuth provider is not configured")
|
||||||
isProviderConfigured = false
|
isProviderConfigured = false
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -79,6 +85,7 @@ func OAuthLoginHandler() gin.HandlerFunc {
|
|||||||
c.Redirect(http.StatusTemporaryRedirect, url)
|
c.Redirect(http.StatusTemporaryRedirect, url)
|
||||||
case constants.SignupMethodGithub:
|
case constants.SignupMethodGithub:
|
||||||
if oauth.OAuthProviders.GithubConfig == nil {
|
if oauth.OAuthProviders.GithubConfig == nil {
|
||||||
|
log.Debug("Github OAuth provider is not configured")
|
||||||
isProviderConfigured = false
|
isProviderConfigured = false
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -88,6 +95,7 @@ func OAuthLoginHandler() gin.HandlerFunc {
|
|||||||
c.Redirect(http.StatusTemporaryRedirect, url)
|
c.Redirect(http.StatusTemporaryRedirect, url)
|
||||||
case constants.SignupMethodFacebook:
|
case constants.SignupMethodFacebook:
|
||||||
if oauth.OAuthProviders.FacebookConfig == nil {
|
if oauth.OAuthProviders.FacebookConfig == nil {
|
||||||
|
log.Debug("Facebook OAuth provider is not configured")
|
||||||
isProviderConfigured = false
|
isProviderConfigured = false
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -96,6 +104,7 @@ func OAuthLoginHandler() gin.HandlerFunc {
|
|||||||
url := oauth.OAuthProviders.FacebookConfig.AuthCodeURL(oauthStateString)
|
url := oauth.OAuthProviders.FacebookConfig.AuthCodeURL(oauthStateString)
|
||||||
c.Redirect(http.StatusTemporaryRedirect, url)
|
c.Redirect(http.StatusTemporaryRedirect, url)
|
||||||
default:
|
default:
|
||||||
|
log.Debug("Invalid oauth provider: ", provider)
|
||||||
c.JSON(422, gin.H{
|
c.JSON(422, gin.H{
|
||||||
"message": "Invalid oauth provider",
|
"message": "Invalid oauth provider",
|
||||||
})
|
})
|
||||||
|
@@ -4,10 +4,12 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
"github.com/authorizerdev/authorizer/server/envstore"
|
||||||
"github.com/authorizerdev/authorizer/server/sessionstore"
|
"github.com/authorizerdev/authorizer/server/sessionstore"
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Revoke handler to revoke refresh token
|
// Revoke handler to revoke refresh token
|
||||||
@@ -15,6 +17,7 @@ func RevokeHandler() gin.HandlerFunc {
|
|||||||
return func(gc *gin.Context) {
|
return func(gc *gin.Context) {
|
||||||
var reqBody map[string]string
|
var reqBody map[string]string
|
||||||
if err := gc.BindJSON(&reqBody); err != nil {
|
if err := gc.BindJSON(&reqBody); err != nil {
|
||||||
|
log.Debug("Error binding JSON: ", err)
|
||||||
gc.JSON(http.StatusBadRequest, gin.H{
|
gc.JSON(http.StatusBadRequest, gin.H{
|
||||||
"error": "error_binding_json",
|
"error": "error_binding_json",
|
||||||
"error_description": err.Error(),
|
"error_description": err.Error(),
|
||||||
@@ -26,6 +29,7 @@ func RevokeHandler() gin.HandlerFunc {
|
|||||||
clientID := strings.TrimSpace(reqBody["client_id"])
|
clientID := strings.TrimSpace(reqBody["client_id"])
|
||||||
|
|
||||||
if clientID == "" {
|
if clientID == "" {
|
||||||
|
log.Debug("Client ID is empty")
|
||||||
gc.JSON(http.StatusBadRequest, gin.H{
|
gc.JSON(http.StatusBadRequest, gin.H{
|
||||||
"error": "client_id_required",
|
"error": "client_id_required",
|
||||||
"error_description": "The client id is required",
|
"error_description": "The client id is required",
|
||||||
@@ -34,6 +38,7 @@ func RevokeHandler() gin.HandlerFunc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if clientID != envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyClientID) {
|
if clientID != envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyClientID) {
|
||||||
|
log.Debug("Client ID is invalid: ", clientID)
|
||||||
gc.JSON(http.StatusBadRequest, gin.H{
|
gc.JSON(http.StatusBadRequest, gin.H{
|
||||||
"error": "invalid_client_id",
|
"error": "invalid_client_id",
|
||||||
"error_description": "The client id is invalid",
|
"error_description": "The client id is invalid",
|
||||||
|
@@ -7,13 +7,15 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/cookie"
|
"github.com/authorizerdev/authorizer/server/cookie"
|
||||||
"github.com/authorizerdev/authorizer/server/db"
|
"github.com/authorizerdev/authorizer/server/db"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
"github.com/authorizerdev/authorizer/server/envstore"
|
||||||
"github.com/authorizerdev/authorizer/server/sessionstore"
|
"github.com/authorizerdev/authorizer/server/sessionstore"
|
||||||
"github.com/authorizerdev/authorizer/server/token"
|
"github.com/authorizerdev/authorizer/server/token"
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// TokenHandler to handle /oauth/token requests
|
// TokenHandler to handle /oauth/token requests
|
||||||
@@ -22,6 +24,7 @@ func TokenHandler() gin.HandlerFunc {
|
|||||||
return func(gc *gin.Context) {
|
return func(gc *gin.Context) {
|
||||||
var reqBody map[string]string
|
var reqBody map[string]string
|
||||||
if err := gc.BindJSON(&reqBody); err != nil {
|
if err := gc.BindJSON(&reqBody); err != nil {
|
||||||
|
log.Debug("Error binding JSON: ", err)
|
||||||
gc.JSON(http.StatusBadRequest, gin.H{
|
gc.JSON(http.StatusBadRequest, gin.H{
|
||||||
"error": "error_binding_json",
|
"error": "error_binding_json",
|
||||||
"error_description": err.Error(),
|
"error_description": err.Error(),
|
||||||
@@ -43,6 +46,7 @@ func TokenHandler() gin.HandlerFunc {
|
|||||||
isAuthorizationCodeGrant := grantType == "authorization_code"
|
isAuthorizationCodeGrant := grantType == "authorization_code"
|
||||||
|
|
||||||
if !isRefreshTokenGrant && !isAuthorizationCodeGrant {
|
if !isRefreshTokenGrant && !isAuthorizationCodeGrant {
|
||||||
|
log.Debug("Invalid grant type: ", grantType)
|
||||||
gc.JSON(http.StatusBadRequest, gin.H{
|
gc.JSON(http.StatusBadRequest, gin.H{
|
||||||
"error": "invalid_grant_type",
|
"error": "invalid_grant_type",
|
||||||
"error_description": "grant_type is invalid",
|
"error_description": "grant_type is invalid",
|
||||||
@@ -50,6 +54,7 @@ func TokenHandler() gin.HandlerFunc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if clientID == "" {
|
if clientID == "" {
|
||||||
|
log.Debug("Client ID is empty")
|
||||||
gc.JSON(http.StatusBadRequest, gin.H{
|
gc.JSON(http.StatusBadRequest, gin.H{
|
||||||
"error": "client_id_required",
|
"error": "client_id_required",
|
||||||
"error_description": "The client id is required",
|
"error_description": "The client id is required",
|
||||||
@@ -58,6 +63,7 @@ func TokenHandler() gin.HandlerFunc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if clientID != envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyClientID) {
|
if clientID != envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyClientID) {
|
||||||
|
log.Debug("Client ID is invalid: ", clientID)
|
||||||
gc.JSON(http.StatusBadRequest, gin.H{
|
gc.JSON(http.StatusBadRequest, gin.H{
|
||||||
"error": "invalid_client_id",
|
"error": "invalid_client_id",
|
||||||
"error_description": "The client id is invalid",
|
"error_description": "The client id is invalid",
|
||||||
@@ -70,6 +76,7 @@ func TokenHandler() gin.HandlerFunc {
|
|||||||
if isAuthorizationCodeGrant {
|
if isAuthorizationCodeGrant {
|
||||||
|
|
||||||
if codeVerifier == "" {
|
if codeVerifier == "" {
|
||||||
|
log.Debug("Code verifier is empty")
|
||||||
gc.JSON(http.StatusBadRequest, gin.H{
|
gc.JSON(http.StatusBadRequest, gin.H{
|
||||||
"error": "invalid_code_verifier",
|
"error": "invalid_code_verifier",
|
||||||
"error_description": "The code verifier is required",
|
"error_description": "The code verifier is required",
|
||||||
@@ -78,6 +85,7 @@ func TokenHandler() gin.HandlerFunc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if code == "" {
|
if code == "" {
|
||||||
|
log.Debug("Code is empty")
|
||||||
gc.JSON(http.StatusBadRequest, gin.H{
|
gc.JSON(http.StatusBadRequest, gin.H{
|
||||||
"error": "invalid_code",
|
"error": "invalid_code",
|
||||||
"error_description": "The code is required",
|
"error_description": "The code is required",
|
||||||
@@ -92,6 +100,7 @@ func TokenHandler() gin.HandlerFunc {
|
|||||||
encryptedCode = strings.ReplaceAll(encryptedCode, "=", "")
|
encryptedCode = strings.ReplaceAll(encryptedCode, "=", "")
|
||||||
sessionData := sessionstore.GetState(encryptedCode)
|
sessionData := sessionstore.GetState(encryptedCode)
|
||||||
if sessionData == "" {
|
if sessionData == "" {
|
||||||
|
log.Debug("Session data is empty")
|
||||||
gc.JSON(http.StatusBadRequest, gin.H{
|
gc.JSON(http.StatusBadRequest, gin.H{
|
||||||
"error": "invalid_code_verifier",
|
"error": "invalid_code_verifier",
|
||||||
"error_description": "The code verifier is invalid",
|
"error_description": "The code verifier is invalid",
|
||||||
@@ -104,6 +113,7 @@ func TokenHandler() gin.HandlerFunc {
|
|||||||
sessionDataSplit := strings.Split(sessionData, "@")
|
sessionDataSplit := strings.Split(sessionData, "@")
|
||||||
|
|
||||||
if sessionDataSplit[0] != code {
|
if sessionDataSplit[0] != code {
|
||||||
|
log.Debug("Invalid code verifier. Unable to split session data")
|
||||||
gc.JSON(http.StatusBadRequest, gin.H{
|
gc.JSON(http.StatusBadRequest, gin.H{
|
||||||
"error": "invalid_code_verifier",
|
"error": "invalid_code_verifier",
|
||||||
"error_description": "The code verifier is invalid",
|
"error_description": "The code verifier is invalid",
|
||||||
@@ -114,6 +124,7 @@ func TokenHandler() gin.HandlerFunc {
|
|||||||
// validate session
|
// validate session
|
||||||
claims, err := token.ValidateBrowserSession(gc, sessionDataSplit[1])
|
claims, err := token.ValidateBrowserSession(gc, sessionDataSplit[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Error validating session: ", err)
|
||||||
gc.JSON(http.StatusUnauthorized, gin.H{
|
gc.JSON(http.StatusUnauthorized, gin.H{
|
||||||
"error": "unauthorized",
|
"error": "unauthorized",
|
||||||
"error_description": "Invalid session data",
|
"error_description": "Invalid session data",
|
||||||
@@ -128,6 +139,7 @@ func TokenHandler() gin.HandlerFunc {
|
|||||||
} else {
|
} else {
|
||||||
// validate refresh token
|
// validate refresh token
|
||||||
if refreshToken == "" {
|
if refreshToken == "" {
|
||||||
|
log.Debug("Refresh token is empty")
|
||||||
gc.JSON(http.StatusBadRequest, gin.H{
|
gc.JSON(http.StatusBadRequest, gin.H{
|
||||||
"error": "invalid_refresh_token",
|
"error": "invalid_refresh_token",
|
||||||
"error_description": "The refresh token is invalid",
|
"error_description": "The refresh token is invalid",
|
||||||
@@ -136,6 +148,7 @@ func TokenHandler() gin.HandlerFunc {
|
|||||||
|
|
||||||
claims, err := token.ValidateRefreshToken(gc, refreshToken)
|
claims, err := token.ValidateRefreshToken(gc, refreshToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Error validating refresh token: ", err)
|
||||||
gc.JSON(http.StatusUnauthorized, gin.H{
|
gc.JSON(http.StatusUnauthorized, gin.H{
|
||||||
"error": "unauthorized",
|
"error": "unauthorized",
|
||||||
"error_description": err.Error(),
|
"error_description": err.Error(),
|
||||||
@@ -156,6 +169,7 @@ func TokenHandler() gin.HandlerFunc {
|
|||||||
|
|
||||||
user, err := db.Provider.GetUserByID(userID)
|
user, err := db.Provider.GetUserByID(userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Error getting user: ", err)
|
||||||
gc.JSON(http.StatusUnauthorized, gin.H{
|
gc.JSON(http.StatusUnauthorized, gin.H{
|
||||||
"error": "unauthorized",
|
"error": "unauthorized",
|
||||||
"error_description": "User not found",
|
"error_description": "User not found",
|
||||||
@@ -165,6 +179,7 @@ func TokenHandler() gin.HandlerFunc {
|
|||||||
|
|
||||||
authToken, err := token.CreateAuthToken(gc, user, roles, scope)
|
authToken, err := token.CreateAuthToken(gc, user, roles, scope)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Error creating auth token: ", err)
|
||||||
gc.JSON(http.StatusUnauthorized, gin.H{
|
gc.JSON(http.StatusUnauthorized, gin.H{
|
||||||
"error": "unauthorized",
|
"error": "unauthorized",
|
||||||
"error_description": "User not found",
|
"error_description": "User not found",
|
||||||
|
@@ -3,15 +3,18 @@ package handlers
|
|||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/db"
|
"github.com/authorizerdev/authorizer/server/db"
|
||||||
"github.com/authorizerdev/authorizer/server/token"
|
"github.com/authorizerdev/authorizer/server/token"
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func UserInfoHandler() gin.HandlerFunc {
|
func UserInfoHandler() gin.HandlerFunc {
|
||||||
return func(gc *gin.Context) {
|
return func(gc *gin.Context) {
|
||||||
accessToken, err := token.GetAccessToken(gc)
|
accessToken, err := token.GetAccessToken(gc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Error getting access token: ", err)
|
||||||
gc.JSON(http.StatusUnauthorized, gin.H{
|
gc.JSON(http.StatusUnauthorized, gin.H{
|
||||||
"error": err.Error(),
|
"error": err.Error(),
|
||||||
})
|
})
|
||||||
@@ -20,6 +23,7 @@ func UserInfoHandler() gin.HandlerFunc {
|
|||||||
|
|
||||||
claims, err := token.ValidateAccessToken(gc, accessToken)
|
claims, err := token.ValidateAccessToken(gc, accessToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Error validating access token: ", err)
|
||||||
gc.JSON(http.StatusUnauthorized, gin.H{
|
gc.JSON(http.StatusUnauthorized, gin.H{
|
||||||
"error": err.Error(),
|
"error": err.Error(),
|
||||||
})
|
})
|
||||||
@@ -29,6 +33,7 @@ func UserInfoHandler() gin.HandlerFunc {
|
|||||||
userID := claims["sub"].(string)
|
userID := claims["sub"].(string)
|
||||||
user, err := db.Provider.GetUserByID(userID)
|
user, err := db.Provider.GetUserByID(userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Error getting user: ", err)
|
||||||
gc.JSON(http.StatusUnauthorized, gin.H{
|
gc.JSON(http.StatusUnauthorized, gin.H{
|
||||||
"error": err.Error(),
|
"error": err.Error(),
|
||||||
})
|
})
|
||||||
|
@@ -6,12 +6,15 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/cookie"
|
"github.com/authorizerdev/authorizer/server/cookie"
|
||||||
"github.com/authorizerdev/authorizer/server/db"
|
"github.com/authorizerdev/authorizer/server/db"
|
||||||
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
"github.com/authorizerdev/authorizer/server/sessionstore"
|
"github.com/authorizerdev/authorizer/server/sessionstore"
|
||||||
"github.com/authorizerdev/authorizer/server/token"
|
"github.com/authorizerdev/authorizer/server/token"
|
||||||
"github.com/authorizerdev/authorizer/server/utils"
|
"github.com/authorizerdev/authorizer/server/utils"
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// VerifyEmailHandler handles the verify email route.
|
// VerifyEmailHandler handles the verify email route.
|
||||||
@@ -23,12 +26,14 @@ func VerifyEmailHandler() gin.HandlerFunc {
|
|||||||
}
|
}
|
||||||
tokenInQuery := c.Query("token")
|
tokenInQuery := c.Query("token")
|
||||||
if tokenInQuery == "" {
|
if tokenInQuery == "" {
|
||||||
|
log.Debug("Token is empty")
|
||||||
c.JSON(400, errorRes)
|
c.JSON(400, errorRes)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
verificationRequest, err := db.Provider.GetVerificationRequestByToken(tokenInQuery)
|
verificationRequest, err := db.Provider.GetVerificationRequestByToken(tokenInQuery)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Error getting verification request: ", err)
|
||||||
errorRes["error_description"] = err.Error()
|
errorRes["error_description"] = err.Error()
|
||||||
c.JSON(400, errorRes)
|
c.JSON(400, errorRes)
|
||||||
return
|
return
|
||||||
@@ -38,6 +43,7 @@ func VerifyEmailHandler() gin.HandlerFunc {
|
|||||||
hostname := utils.GetHost(c)
|
hostname := utils.GetHost(c)
|
||||||
claim, err := token.ParseJWTToken(tokenInQuery, hostname, verificationRequest.Nonce, verificationRequest.Email)
|
claim, err := token.ParseJWTToken(tokenInQuery, hostname, verificationRequest.Nonce, verificationRequest.Email)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Error parsing token: ", err)
|
||||||
errorRes["error_description"] = err.Error()
|
errorRes["error_description"] = err.Error()
|
||||||
c.JSON(400, errorRes)
|
c.JSON(400, errorRes)
|
||||||
return
|
return
|
||||||
@@ -45,6 +51,7 @@ func VerifyEmailHandler() gin.HandlerFunc {
|
|||||||
|
|
||||||
user, err := db.Provider.GetUserByEmail(claim["sub"].(string))
|
user, err := db.Provider.GetUserByEmail(claim["sub"].(string))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Error getting user: ", err)
|
||||||
errorRes["error_description"] = err.Error()
|
errorRes["error_description"] = err.Error()
|
||||||
c.JSON(400, errorRes)
|
c.JSON(400, errorRes)
|
||||||
return
|
return
|
||||||
@@ -78,6 +85,7 @@ func VerifyEmailHandler() gin.HandlerFunc {
|
|||||||
}
|
}
|
||||||
authToken, err := token.CreateAuthToken(c, user, roles, scope)
|
authToken, err := token.CreateAuthToken(c, user, roles, scope)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Error creating auth token: ", err)
|
||||||
errorRes["error_description"] = err.Error()
|
errorRes["error_description"] = err.Error()
|
||||||
c.JSON(500, errorRes)
|
c.JSON(500, errorRes)
|
||||||
return
|
return
|
||||||
@@ -109,7 +117,11 @@ func VerifyEmailHandler() gin.HandlerFunc {
|
|||||||
redirectURL = redirectURL + "?" + params
|
redirectURL = redirectURL + "?" + params
|
||||||
}
|
}
|
||||||
|
|
||||||
go utils.SaveSessionInDB(c, user.ID)
|
go db.Provider.AddSession(models.Session{
|
||||||
|
UserID: user.ID,
|
||||||
|
UserAgent: utils.GetUserAgent(c.Request),
|
||||||
|
IP: utils.GetIP(c.Request),
|
||||||
|
})
|
||||||
|
|
||||||
c.Redirect(http.StatusTemporaryRedirect, redirectURL)
|
c.Redirect(http.StatusTemporaryRedirect, redirectURL)
|
||||||
}
|
}
|
||||||
|
@@ -2,7 +2,9 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"log"
|
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/db"
|
"github.com/authorizerdev/authorizer/server/db"
|
||||||
@@ -15,25 +17,63 @@ import (
|
|||||||
|
|
||||||
var VERSION string
|
var VERSION string
|
||||||
|
|
||||||
|
type LogUTCFormatter struct {
|
||||||
|
log.Formatter
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u LogUTCFormatter) Format(e *log.Entry) ([]byte, error) {
|
||||||
|
e.Time = e.Time.UTC()
|
||||||
|
return u.Formatter.Format(e)
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
envstore.ARG_DB_URL = flag.String("database_url", "", "Database connection string")
|
envstore.ARG_DB_URL = flag.String("database_url", "", "Database connection string")
|
||||||
envstore.ARG_DB_TYPE = flag.String("database_type", "", "Database type, possible values are postgres,mysql,sqlite")
|
envstore.ARG_DB_TYPE = flag.String("database_type", "", "Database type, possible values are postgres,mysql,sqlite")
|
||||||
envstore.ARG_ENV_FILE = flag.String("env_file", "", "Env file path")
|
envstore.ARG_ENV_FILE = flag.String("env_file", "", "Env file path")
|
||||||
|
envstore.ARG_LOG_LEVEL = flag.String("log_level", "info", "Log level, possible values are debug,info,warn,error,fatal,panic")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
log.Println("=> version:", VERSION)
|
// global log level
|
||||||
|
logrus.SetFormatter(LogUTCFormatter{&logrus.JSONFormatter{}})
|
||||||
|
logrus.SetReportCaller(true)
|
||||||
|
|
||||||
|
// log instance for gin server
|
||||||
|
log := logrus.New()
|
||||||
|
log.SetFormatter(LogUTCFormatter{&logrus.JSONFormatter{}})
|
||||||
|
log.SetReportCaller(true)
|
||||||
|
|
||||||
|
var logLevel logrus.Level
|
||||||
|
switch *envstore.ARG_LOG_LEVEL {
|
||||||
|
case "debug":
|
||||||
|
logLevel = logrus.DebugLevel
|
||||||
|
case "info":
|
||||||
|
logLevel = logrus.InfoLevel
|
||||||
|
case "warn":
|
||||||
|
logLevel = logrus.WarnLevel
|
||||||
|
case "error":
|
||||||
|
logLevel = logrus.ErrorLevel
|
||||||
|
case "fatal":
|
||||||
|
logLevel = logrus.FatalLevel
|
||||||
|
case "panic":
|
||||||
|
logLevel = logrus.PanicLevel
|
||||||
|
default:
|
||||||
|
logLevel = logrus.InfoLevel
|
||||||
|
}
|
||||||
|
logrus.SetLevel(logLevel)
|
||||||
|
log.SetLevel(logLevel)
|
||||||
|
|
||||||
constants.VERSION = VERSION
|
constants.VERSION = VERSION
|
||||||
|
|
||||||
// initialize required envs (mainly db & env file path)
|
// initialize required envs (mainly db & env file path)
|
||||||
err := env.InitRequiredEnv()
|
err := env.InitRequiredEnv()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("Error while initializing required envs:", err)
|
log.Fatal("Error while initializing required envs: ", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// initialize db provider
|
// initialize db provider
|
||||||
err = db.InitDB()
|
err = db.InitDB()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalln("Error while initializing db:", err)
|
log.Fatalln("Error while initializing db: ", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// initialize all envs
|
// initialize all envs
|
||||||
@@ -46,21 +86,22 @@ func main() {
|
|||||||
// persist all envs
|
// persist all envs
|
||||||
err = env.PersistEnv()
|
err = env.PersistEnv()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalln("Error while persisting env:", err)
|
log.Fatalln("Error while persisting env: ", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// initialize session store (redis or in-memory based on env)
|
// initialize session store (redis or in-memory based on env)
|
||||||
err = sessionstore.InitSession()
|
err = sessionstore.InitSession()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalln("Error while initializing session store:", err)
|
log.Fatalln("Error while initializing session store: ", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// initialize oauth providers based on env
|
// initialize oauth providers based on env
|
||||||
err = oauth.InitOAuth()
|
err = oauth.InitOAuth()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalln("Error while initializing oauth:", err)
|
log.Fatalln("Error while initializing oauth: ", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
router := routes.InitRouter()
|
router := routes.InitRouter(log)
|
||||||
|
log.Info("Starting Authorizer: ", VERSION)
|
||||||
router.Run(":" + envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyPort))
|
router.Run(":" + envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyPort))
|
||||||
}
|
}
|
||||||
|
@@ -15,7 +15,7 @@ func CORSMiddleware() gin.HandlerFunc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
|
c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
|
||||||
c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With")
|
c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With, X-authorizer-url")
|
||||||
c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS, GET, PUT")
|
c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS, GET, PUT")
|
||||||
|
|
||||||
if c.Request.Method == "OPTIONS" {
|
if c.Request.Method == "OPTIONS" {
|
||||||
|
78
server/middlewares/log.go
Normal file
78
server/middlewares/log.go
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
package middlewares
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
var timeFormat = "02/Jan/2006:15:04:05 -0700"
|
||||||
|
|
||||||
|
// Logger is the logrus logger handler
|
||||||
|
func Logger(logger logrus.FieldLogger, notLogged ...string) gin.HandlerFunc {
|
||||||
|
hostname, err := os.Hostname()
|
||||||
|
if err != nil {
|
||||||
|
hostname = "unknown"
|
||||||
|
}
|
||||||
|
|
||||||
|
var skip map[string]struct{}
|
||||||
|
|
||||||
|
if length := len(notLogged); length > 0 {
|
||||||
|
skip = make(map[string]struct{}, length)
|
||||||
|
|
||||||
|
for _, p := range notLogged {
|
||||||
|
skip[p] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return func(c *gin.Context) {
|
||||||
|
// other handler can change c.Path so:
|
||||||
|
path := c.Request.URL.Path
|
||||||
|
start := time.Now()
|
||||||
|
c.Next()
|
||||||
|
stop := time.Since(start)
|
||||||
|
latency := int(math.Ceil(float64(stop.Nanoseconds()) / 1000000.0))
|
||||||
|
statusCode := c.Writer.Status()
|
||||||
|
clientIP := c.ClientIP()
|
||||||
|
clientUserAgent := c.Request.UserAgent()
|
||||||
|
referer := c.Request.Referer()
|
||||||
|
dataLength := c.Writer.Size()
|
||||||
|
if dataLength < 0 {
|
||||||
|
dataLength = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := skip[path]; ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
entry := logger.WithFields(logrus.Fields{
|
||||||
|
"hostname": hostname,
|
||||||
|
"statusCode": statusCode,
|
||||||
|
"latency": latency, // time to process
|
||||||
|
"clientIP": clientIP,
|
||||||
|
"method": c.Request.Method,
|
||||||
|
"path": path,
|
||||||
|
"referer": referer,
|
||||||
|
"dataLength": dataLength,
|
||||||
|
"userAgent": clientUserAgent,
|
||||||
|
})
|
||||||
|
|
||||||
|
if len(c.Errors) > 0 {
|
||||||
|
entry.Error(c.Errors.ByType(gin.ErrorTypePrivate).String())
|
||||||
|
} else {
|
||||||
|
msg := fmt.Sprintf("%s - %s [%s] \"%s %s\" %d %d \"%s\" \"%s\" (%dms)", clientIP, hostname, time.Now().Format(timeFormat), c.Request.Method, path, statusCode, dataLength, referer, clientUserAgent, latency)
|
||||||
|
if statusCode >= http.StatusInternalServerError {
|
||||||
|
entry.Error(msg)
|
||||||
|
} else if statusCode >= http.StatusBadRequest {
|
||||||
|
entry.Warn(msg)
|
||||||
|
} else {
|
||||||
|
entry.Info(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -3,12 +3,13 @@ package oauth
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
|
||||||
"github.com/coreos/go-oidc/v3/oidc"
|
"github.com/coreos/go-oidc/v3/oidc"
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
facebookOAuth2 "golang.org/x/oauth2/facebook"
|
facebookOAuth2 "golang.org/x/oauth2/facebook"
|
||||||
githubOAuth2 "golang.org/x/oauth2/github"
|
githubOAuth2 "golang.org/x/oauth2/github"
|
||||||
|
|
||||||
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
|
"github.com/authorizerdev/authorizer/server/envstore"
|
||||||
)
|
)
|
||||||
|
|
||||||
// OAuthProviders is a struct that contains reference all the OAuth providers
|
// OAuthProviders is a struct that contains reference all the OAuth providers
|
||||||
|
@@ -4,6 +4,8 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/cookie"
|
"github.com/authorizerdev/authorizer/server/cookie"
|
||||||
"github.com/authorizerdev/authorizer/server/crypto"
|
"github.com/authorizerdev/authorizer/server/crypto"
|
||||||
@@ -14,15 +16,17 @@ import (
|
|||||||
|
|
||||||
// AdminLoginResolver is a resolver for admin login mutation
|
// AdminLoginResolver is a resolver for admin login mutation
|
||||||
func AdminLoginResolver(ctx context.Context, params model.AdminLoginInput) (*model.Response, error) {
|
func AdminLoginResolver(ctx context.Context, params model.AdminLoginInput) (*model.Response, error) {
|
||||||
gc, err := utils.GinContextFromContext(ctx)
|
|
||||||
var res *model.Response
|
var res *model.Response
|
||||||
|
|
||||||
|
gc, err := utils.GinContextFromContext(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to get GinContext: ", err)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
adminSecret := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret)
|
adminSecret := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret)
|
||||||
if params.AdminSecret != adminSecret {
|
if params.AdminSecret != adminSecret {
|
||||||
|
log.Debug("Admin secret is not correct")
|
||||||
return res, fmt.Errorf(`invalid admin secret`)
|
return res, fmt.Errorf(`invalid admin secret`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -4,6 +4,8 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/cookie"
|
"github.com/authorizerdev/authorizer/server/cookie"
|
||||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
"github.com/authorizerdev/authorizer/server/token"
|
"github.com/authorizerdev/authorizer/server/token"
|
||||||
@@ -12,14 +14,16 @@ import (
|
|||||||
|
|
||||||
// AdminLogoutResolver is a resolver for admin logout mutation
|
// AdminLogoutResolver is a resolver for admin logout mutation
|
||||||
func AdminLogoutResolver(ctx context.Context) (*model.Response, error) {
|
func AdminLogoutResolver(ctx context.Context) (*model.Response, error) {
|
||||||
gc, err := utils.GinContextFromContext(ctx)
|
|
||||||
var res *model.Response
|
var res *model.Response
|
||||||
|
|
||||||
|
gc, err := utils.GinContextFromContext(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to get GinContext: ", err)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !token.IsSuperAdmin(gc) {
|
if !token.IsSuperAdmin(gc) {
|
||||||
|
log.Debug("Admin is not logged in")
|
||||||
return res, fmt.Errorf("unauthorized")
|
return res, fmt.Errorf("unauthorized")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -4,6 +4,8 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/cookie"
|
"github.com/authorizerdev/authorizer/server/cookie"
|
||||||
"github.com/authorizerdev/authorizer/server/crypto"
|
"github.com/authorizerdev/authorizer/server/crypto"
|
||||||
@@ -15,19 +17,22 @@ import (
|
|||||||
|
|
||||||
// AdminSessionResolver is a resolver for admin session query
|
// AdminSessionResolver is a resolver for admin session query
|
||||||
func AdminSessionResolver(ctx context.Context) (*model.Response, error) {
|
func AdminSessionResolver(ctx context.Context) (*model.Response, error) {
|
||||||
gc, err := utils.GinContextFromContext(ctx)
|
|
||||||
var res *model.Response
|
var res *model.Response
|
||||||
|
|
||||||
|
gc, err := utils.GinContextFromContext(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to get GinContext: ", err)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !token.IsSuperAdmin(gc) {
|
if !token.IsSuperAdmin(gc) {
|
||||||
|
log.Debug("Not logged in as super admin")
|
||||||
return res, fmt.Errorf("unauthorized")
|
return res, fmt.Errorf("unauthorized")
|
||||||
}
|
}
|
||||||
|
|
||||||
hashedKey, err := crypto.EncryptPassword(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret))
|
hashedKey, err := crypto.EncryptPassword(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to encrypt key: ", err)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
cookie.SetAdminCookie(gc, hashedKey)
|
cookie.SetAdminCookie(gc, hashedKey)
|
||||||
|
@@ -6,6 +6,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/cookie"
|
"github.com/authorizerdev/authorizer/server/cookie"
|
||||||
"github.com/authorizerdev/authorizer/server/crypto"
|
"github.com/authorizerdev/authorizer/server/crypto"
|
||||||
@@ -17,19 +19,22 @@ import (
|
|||||||
|
|
||||||
// AdminSignupResolver is a resolver for admin signup mutation
|
// AdminSignupResolver is a resolver for admin signup mutation
|
||||||
func AdminSignupResolver(ctx context.Context, params model.AdminSignupInput) (*model.Response, error) {
|
func AdminSignupResolver(ctx context.Context, params model.AdminSignupInput) (*model.Response, error) {
|
||||||
gc, err := utils.GinContextFromContext(ctx)
|
|
||||||
var res *model.Response
|
var res *model.Response
|
||||||
|
|
||||||
|
gc, err := utils.GinContextFromContext(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to get GinContext: ", err)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.TrimSpace(params.AdminSecret) == "" {
|
if strings.TrimSpace(params.AdminSecret) == "" {
|
||||||
|
log.Debug("Admin secret is empty")
|
||||||
err = fmt.Errorf("please select secure admin secret")
|
err = fmt.Errorf("please select secure admin secret")
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(params.AdminSecret) < 6 {
|
if len(params.AdminSecret) < 6 {
|
||||||
|
log.Debug("Admin secret is too short")
|
||||||
err = fmt.Errorf("admin secret must be at least 6 characters")
|
err = fmt.Errorf("admin secret must be at least 6 characters")
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
@@ -37,6 +42,7 @@ func AdminSignupResolver(ctx context.Context, params model.AdminSignupInput) (*m
|
|||||||
adminSecret := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret)
|
adminSecret := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret)
|
||||||
|
|
||||||
if adminSecret != "" {
|
if adminSecret != "" {
|
||||||
|
log.Debug("Admin secret is already set")
|
||||||
err = fmt.Errorf("admin sign up already completed")
|
err = fmt.Errorf("admin sign up already completed")
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
@@ -47,30 +53,36 @@ func AdminSignupResolver(ctx context.Context, params model.AdminSignupInput) (*m
|
|||||||
|
|
||||||
jsonBytes, err := json.Marshal(envstore.EnvStoreObj.GetEnvStoreClone())
|
jsonBytes, err := json.Marshal(envstore.EnvStoreObj.GetEnvStoreClone())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to marshal envstore: ", err)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := json.Unmarshal(jsonBytes, &storeData); err != nil {
|
if err := json.Unmarshal(jsonBytes, &storeData); err != nil {
|
||||||
|
log.Debug("Failed to unmarshal envstore: ", err)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
env, err := db.Provider.GetEnv()
|
env, err := db.Provider.GetEnv()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to get env: ", err)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
envData, err := crypto.EncryptEnvData(storeData)
|
envData, err := crypto.EncryptEnvData(storeData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to encrypt envstore: ", err)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
env.EnvData = envData
|
env.EnvData = envData
|
||||||
if _, err := db.Provider.UpdateEnv(env); err != nil {
|
if _, err := db.Provider.UpdateEnv(env); err != nil {
|
||||||
|
log.Debug("Failed to update env: ", err)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
hashedKey, err := crypto.EncryptPassword(params.AdminSecret)
|
hashedKey, err := crypto.EncryptPassword(params.AdminSecret)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to encrypt admin session key: ", err)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
cookie.SetAdminCookie(gc, hashedKey)
|
cookie.SetAdminCookie(gc, hashedKey)
|
||||||
|
@@ -3,7 +3,8 @@ package resolvers
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/db"
|
"github.com/authorizerdev/authorizer/server/db"
|
||||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
@@ -14,18 +15,26 @@ import (
|
|||||||
|
|
||||||
// DeleteUserResolver is a resolver for delete user mutation
|
// DeleteUserResolver is a resolver for delete user mutation
|
||||||
func DeleteUserResolver(ctx context.Context, params model.DeleteUserInput) (*model.Response, error) {
|
func DeleteUserResolver(ctx context.Context, params model.DeleteUserInput) (*model.Response, error) {
|
||||||
gc, err := utils.GinContextFromContext(ctx)
|
|
||||||
var res *model.Response
|
var res *model.Response
|
||||||
|
|
||||||
|
gc, err := utils.GinContextFromContext(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to get GinContext: ", err)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !token.IsSuperAdmin(gc) {
|
if !token.IsSuperAdmin(gc) {
|
||||||
|
log.Debug("Not logged in as super admin")
|
||||||
return res, fmt.Errorf("unauthorized")
|
return res, fmt.Errorf("unauthorized")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log := log.WithFields(log.Fields{
|
||||||
|
"email": params.Email,
|
||||||
|
})
|
||||||
|
|
||||||
user, err := db.Provider.GetUserByEmail(params.Email)
|
user, err := db.Provider.GetUserByEmail(params.Email)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to get user from DB: ", err)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,7 +42,7 @@ func DeleteUserResolver(ctx context.Context, params model.DeleteUserInput) (*mod
|
|||||||
|
|
||||||
err = db.Provider.DeleteUser(user)
|
err = db.Provider.DeleteUser(user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error deleting user:", err)
|
log.Debug("Failed to delete user: ", err)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -3,7 +3,8 @@ package resolvers
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/db"
|
"github.com/authorizerdev/authorizer/server/db"
|
||||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
@@ -13,18 +14,26 @@ import (
|
|||||||
|
|
||||||
// EnableAccessResolver is a resolver for enabling user access
|
// EnableAccessResolver is a resolver for enabling user access
|
||||||
func EnableAccessResolver(ctx context.Context, params model.UpdateAccessInput) (*model.Response, error) {
|
func EnableAccessResolver(ctx context.Context, params model.UpdateAccessInput) (*model.Response, error) {
|
||||||
gc, err := utils.GinContextFromContext(ctx)
|
|
||||||
var res *model.Response
|
var res *model.Response
|
||||||
|
|
||||||
|
gc, err := utils.GinContextFromContext(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to get GinContext: ", err)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !token.IsSuperAdmin(gc) {
|
if !token.IsSuperAdmin(gc) {
|
||||||
|
log.Debug("Not logged in as super admin.")
|
||||||
return res, fmt.Errorf("unauthorized")
|
return res, fmt.Errorf("unauthorized")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log := log.WithFields(log.Fields{
|
||||||
|
"user_id": params.UserID,
|
||||||
|
})
|
||||||
|
|
||||||
user, err := db.Provider.GetUserByID(params.UserID)
|
user, err := db.Provider.GetUserByID(params.UserID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to get user from DB: ", err)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,7 +41,7 @@ func EnableAccessResolver(ctx context.Context, params model.UpdateAccessInput) (
|
|||||||
|
|
||||||
user, err = db.Provider.UpdateUser(user)
|
user, err = db.Provider.UpdateUser(user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error updating user:", err)
|
log.Debug("Failed to update user: ", err)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -4,6 +4,8 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
"github.com/authorizerdev/authorizer/server/envstore"
|
||||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
@@ -14,14 +16,16 @@ import (
|
|||||||
// EnvResolver is a resolver for config query
|
// EnvResolver is a resolver for config query
|
||||||
// This is admin only query
|
// This is admin only query
|
||||||
func EnvResolver(ctx context.Context) (*model.Env, error) {
|
func EnvResolver(ctx context.Context) (*model.Env, error) {
|
||||||
gc, err := utils.GinContextFromContext(ctx)
|
|
||||||
var res *model.Env
|
var res *model.Env
|
||||||
|
|
||||||
|
gc, err := utils.GinContextFromContext(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to get GinContext: ", err)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !token.IsSuperAdmin(gc) {
|
if !token.IsSuperAdmin(gc) {
|
||||||
|
log.Debug("Not logged in as super admin.")
|
||||||
return res, fmt.Errorf("unauthorized")
|
return res, fmt.Errorf("unauthorized")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,6 +38,10 @@ func EnvResolver(ctx context.Context) (*model.Env, error) {
|
|||||||
databaseURL := store.StringEnv[constants.EnvKeyDatabaseURL]
|
databaseURL := store.StringEnv[constants.EnvKeyDatabaseURL]
|
||||||
databaseName := store.StringEnv[constants.EnvKeyDatabaseName]
|
databaseName := store.StringEnv[constants.EnvKeyDatabaseName]
|
||||||
databaseType := store.StringEnv[constants.EnvKeyDatabaseType]
|
databaseType := store.StringEnv[constants.EnvKeyDatabaseType]
|
||||||
|
databaseUsername := store.StringEnv[constants.EnvKeyDatabaseUsername]
|
||||||
|
databasePassword := store.StringEnv[constants.EnvKeyDatabasePassword]
|
||||||
|
databaseHost := store.StringEnv[constants.EnvKeyDatabaseHost]
|
||||||
|
databasePort := store.StringEnv[constants.EnvKeyDatabasePort]
|
||||||
customAccessTokenScript := store.StringEnv[constants.EnvKeyCustomAccessTokenScript]
|
customAccessTokenScript := store.StringEnv[constants.EnvKeyCustomAccessTokenScript]
|
||||||
smtpHost := store.StringEnv[constants.EnvKeySmtpHost]
|
smtpHost := store.StringEnv[constants.EnvKeySmtpHost]
|
||||||
smtpPort := store.StringEnv[constants.EnvKeySmtpPort]
|
smtpPort := store.StringEnv[constants.EnvKeySmtpPort]
|
||||||
@@ -77,6 +85,10 @@ func EnvResolver(ctx context.Context) (*model.Env, error) {
|
|||||||
DatabaseName: databaseName,
|
DatabaseName: databaseName,
|
||||||
DatabaseURL: databaseURL,
|
DatabaseURL: databaseURL,
|
||||||
DatabaseType: databaseType,
|
DatabaseType: databaseType,
|
||||||
|
DatabaseUsername: databaseUsername,
|
||||||
|
DatabasePassword: databasePassword,
|
||||||
|
DatabaseHost: databaseHost,
|
||||||
|
DatabasePort: databasePort,
|
||||||
ClientID: clientID,
|
ClientID: clientID,
|
||||||
ClientSecret: clientSecret,
|
ClientSecret: clientSecret,
|
||||||
CustomAccessTokenScript: &customAccessTokenScript,
|
CustomAccessTokenScript: &customAccessTokenScript,
|
||||||
|
@@ -3,10 +3,11 @@ package resolvers
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/db"
|
"github.com/authorizerdev/authorizer/server/db"
|
||||||
"github.com/authorizerdev/authorizer/server/db/models"
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
@@ -19,28 +20,38 @@ import (
|
|||||||
|
|
||||||
// ForgotPasswordResolver is a resolver for forgot password mutation
|
// ForgotPasswordResolver is a resolver for forgot password mutation
|
||||||
func ForgotPasswordResolver(ctx context.Context, params model.ForgotPasswordInput) (*model.Response, error) {
|
func ForgotPasswordResolver(ctx context.Context, params model.ForgotPasswordInput) (*model.Response, error) {
|
||||||
gc, err := utils.GinContextFromContext(ctx)
|
|
||||||
var res *model.Response
|
var res *model.Response
|
||||||
|
|
||||||
|
gc, err := utils.GinContextFromContext(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to get GinContext: ", err)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableBasicAuthentication) {
|
if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableBasicAuthentication) {
|
||||||
|
log.Debug("Basic authentication is disabled")
|
||||||
return res, fmt.Errorf(`basic authentication is disabled for this instance`)
|
return res, fmt.Errorf(`basic authentication is disabled for this instance`)
|
||||||
}
|
}
|
||||||
params.Email = strings.ToLower(params.Email)
|
params.Email = strings.ToLower(params.Email)
|
||||||
|
|
||||||
if !utils.IsValidEmail(params.Email) {
|
if !utils.IsValidEmail(params.Email) {
|
||||||
|
log.Debug("Invalid email address: ", params.Email)
|
||||||
return res, fmt.Errorf("invalid email")
|
return res, fmt.Errorf("invalid email")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log := log.WithFields(log.Fields{
|
||||||
|
"email": params.Email,
|
||||||
|
})
|
||||||
_, err = db.Provider.GetUserByEmail(params.Email)
|
_, err = db.Provider.GetUserByEmail(params.Email)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("User not found: ", err)
|
||||||
return res, fmt.Errorf(`user with this email not found`)
|
return res, fmt.Errorf(`user with this email not found`)
|
||||||
}
|
}
|
||||||
|
|
||||||
hostname := utils.GetHost(gc)
|
hostname := utils.GetHost(gc)
|
||||||
_, nonceHash, err := utils.GenerateNonce()
|
_, nonceHash, err := utils.GenerateNonce()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to generate nonce: ", err)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
redirectURL := utils.GetAppURL(gc) + "/reset-password"
|
redirectURL := utils.GetAppURL(gc) + "/reset-password"
|
||||||
@@ -50,9 +61,10 @@ func ForgotPasswordResolver(ctx context.Context, params model.ForgotPasswordInpu
|
|||||||
|
|
||||||
verificationToken, err := token.CreateVerificationToken(params.Email, constants.VerificationTypeForgotPassword, hostname, nonceHash, redirectURL)
|
verificationToken, err := token.CreateVerificationToken(params.Email, constants.VerificationTypeForgotPassword, hostname, nonceHash, redirectURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(`error generating token`, err)
|
log.Debug("Failed to create verification token", err)
|
||||||
|
return res, err
|
||||||
}
|
}
|
||||||
db.Provider.AddVerificationRequest(models.VerificationRequest{
|
_, err = db.Provider.AddVerificationRequest(models.VerificationRequest{
|
||||||
Token: verificationToken,
|
Token: verificationToken,
|
||||||
Identifier: constants.VerificationTypeForgotPassword,
|
Identifier: constants.VerificationTypeForgotPassword,
|
||||||
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
|
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
|
||||||
@@ -60,6 +72,10 @@ func ForgotPasswordResolver(ctx context.Context, params model.ForgotPasswordInpu
|
|||||||
Nonce: nonceHash,
|
Nonce: nonceHash,
|
||||||
RedirectURI: redirectURL,
|
RedirectURI: redirectURL,
|
||||||
})
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("Failed to add verification request", err)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
// exec it as go routin so that we can reduce the api latency
|
// exec it as go routin so that we can reduce the api latency
|
||||||
go email.SendForgotPasswordMail(params.Email, verificationToken, hostname)
|
go email.SendForgotPasswordMail(params.Email, verificationToken, hostname)
|
||||||
|
@@ -10,16 +10,19 @@ import (
|
|||||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
"github.com/authorizerdev/authorizer/server/token"
|
"github.com/authorizerdev/authorizer/server/token"
|
||||||
"github.com/authorizerdev/authorizer/server/utils"
|
"github.com/authorizerdev/authorizer/server/utils"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GenerateJWTKeysResolver mutation to generate new jwt keys
|
// GenerateJWTKeysResolver mutation to generate new jwt keys
|
||||||
func GenerateJWTKeysResolver(ctx context.Context, params model.GenerateJWTKeysInput) (*model.GenerateJWTKeysResponse, error) {
|
func GenerateJWTKeysResolver(ctx context.Context, params model.GenerateJWTKeysInput) (*model.GenerateJWTKeysResponse, error) {
|
||||||
gc, err := utils.GinContextFromContext(ctx)
|
gc, err := utils.GinContextFromContext(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to get GinContext: ", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !token.IsSuperAdmin(gc) {
|
if !token.IsSuperAdmin(gc) {
|
||||||
|
log.Debug("Not logged in as super admin")
|
||||||
return nil, fmt.Errorf("unauthorized")
|
return nil, fmt.Errorf("unauthorized")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,6 +30,7 @@ func GenerateJWTKeysResolver(ctx context.Context, params model.GenerateJWTKeysIn
|
|||||||
if crypto.IsHMACA(params.Type) {
|
if crypto.IsHMACA(params.Type) {
|
||||||
secret, _, err := crypto.NewHMACKey(params.Type, clientID)
|
secret, _, err := crypto.NewHMACKey(params.Type, clientID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to generate new HMAC key: ", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &model.GenerateJWTKeysResponse{
|
return &model.GenerateJWTKeysResponse{
|
||||||
@@ -37,6 +41,7 @@ func GenerateJWTKeysResolver(ctx context.Context, params model.GenerateJWTKeysIn
|
|||||||
if crypto.IsRSA(params.Type) {
|
if crypto.IsRSA(params.Type) {
|
||||||
_, privateKey, publicKey, _, err := crypto.NewRSAKey(params.Type, clientID)
|
_, privateKey, publicKey, _, err := crypto.NewRSAKey(params.Type, clientID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to generate new RSA key: ", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &model.GenerateJWTKeysResponse{
|
return &model.GenerateJWTKeysResponse{
|
||||||
@@ -48,6 +53,7 @@ func GenerateJWTKeysResolver(ctx context.Context, params model.GenerateJWTKeysIn
|
|||||||
if crypto.IsECDSA(params.Type) {
|
if crypto.IsECDSA(params.Type) {
|
||||||
_, privateKey, publicKey, _, err := crypto.NewECDSAKey(params.Type, clientID)
|
_, privateKey, publicKey, _, err := crypto.NewECDSAKey(params.Type, clientID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to generate new ECDSA key: ", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &model.GenerateJWTKeysResponse{
|
return &model.GenerateJWTKeysResponse{
|
||||||
@@ -56,5 +62,6 @@ func GenerateJWTKeysResolver(ctx context.Context, params model.GenerateJWTKeysIn
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Debug("Invalid algorithm: ", params.Type)
|
||||||
return nil, fmt.Errorf("invalid algorithm")
|
return nil, fmt.Errorf("invalid algorithm")
|
||||||
}
|
}
|
||||||
|
@@ -4,10 +4,11 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/db"
|
"github.com/authorizerdev/authorizer/server/db"
|
||||||
"github.com/authorizerdev/authorizer/server/db/models"
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
@@ -22,19 +23,23 @@ import (
|
|||||||
func InviteMembersResolver(ctx context.Context, params model.InviteMemberInput) (*model.Response, error) {
|
func InviteMembersResolver(ctx context.Context, params model.InviteMemberInput) (*model.Response, error) {
|
||||||
gc, err := utils.GinContextFromContext(ctx)
|
gc, err := utils.GinContextFromContext(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to get GinContext: ", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !token.IsSuperAdmin(gc) {
|
if !token.IsSuperAdmin(gc) {
|
||||||
|
log.Debug("Not logged in as super admin.")
|
||||||
return nil, errors.New("unauthorized")
|
return nil, errors.New("unauthorized")
|
||||||
}
|
}
|
||||||
|
|
||||||
// this feature is only allowed if email server is configured
|
// this feature is only allowed if email server is configured
|
||||||
if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableEmailVerification) {
|
if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableEmailVerification) {
|
||||||
|
log.Debug("Email server is not configured")
|
||||||
return nil, errors.New("email sending is disabled")
|
return nil, errors.New("email sending is disabled")
|
||||||
}
|
}
|
||||||
|
|
||||||
if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableBasicAuthentication) && envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableMagicLinkLogin) {
|
if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableBasicAuthentication) && envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableMagicLinkLogin) {
|
||||||
|
log.Debug("Basic authentication and Magic link login is disabled.")
|
||||||
return nil, errors.New("either basic authentication or magic link login is required")
|
return nil, errors.New("either basic authentication or magic link login is required")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,6 +52,7 @@ func InviteMembersResolver(ctx context.Context, params model.InviteMemberInput)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(emails) == 0 {
|
if len(emails) == 0 {
|
||||||
|
log.Debug("No valid email addresses")
|
||||||
return nil, errors.New("no valid emails found")
|
return nil, errors.New("no valid emails found")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,14 +62,15 @@ func InviteMembersResolver(ctx context.Context, params model.InviteMemberInput)
|
|||||||
for _, email := range emails {
|
for _, email := range emails {
|
||||||
_, err := db.Provider.GetUserByEmail(email)
|
_, err := db.Provider.GetUserByEmail(email)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("%s user not found. inviting user.", email)
|
log.Debugf("User with %s email not found, so inviting user", email)
|
||||||
newEmails = append(newEmails, email)
|
newEmails = append(newEmails, email)
|
||||||
} else {
|
} else {
|
||||||
log.Println("%s user already exists. skipping.", email)
|
log.Debugf("User with %s email already exists, so not inviting user", email)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(newEmails) == 0 {
|
if len(newEmails) == 0 {
|
||||||
|
log.Debug("No new emails found.")
|
||||||
return nil, errors.New("all emails already exist")
|
return nil, errors.New("all emails already exist")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,7 +97,7 @@ func InviteMembersResolver(ctx context.Context, params model.InviteMemberInput)
|
|||||||
|
|
||||||
verificationToken, err := token.CreateVerificationToken(email, constants.VerificationTypeForgotPassword, hostname, nonceHash, redirectURL)
|
verificationToken, err := token.CreateVerificationToken(email, constants.VerificationTypeForgotPassword, hostname, nonceHash, redirectURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(`error generating token`, err)
|
log.Debug("Failed to create verification token: ", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
verificationRequest := models.VerificationRequest{
|
verificationRequest := models.VerificationRequest{
|
||||||
@@ -116,13 +123,13 @@ func InviteMembersResolver(ctx context.Context, params model.InviteMemberInput)
|
|||||||
|
|
||||||
user, err = db.Provider.AddUser(user)
|
user, err = db.Provider.AddUser(user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("error inviting user: %s, err: %v", email, err)
|
log.Debugf("Error adding user: %s, err: %v", email, err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = db.Provider.AddVerificationRequest(verificationRequest)
|
_, err = db.Provider.AddVerificationRequest(verificationRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("error inviting user: %s, err: %v", email, err)
|
log.Debugf("Error adding verification request: %s, err: %v", email, err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -3,61 +3,74 @@ package resolvers
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"golang.org/x/crypto/bcrypt"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/cookie"
|
"github.com/authorizerdev/authorizer/server/cookie"
|
||||||
"github.com/authorizerdev/authorizer/server/db"
|
"github.com/authorizerdev/authorizer/server/db"
|
||||||
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
"github.com/authorizerdev/authorizer/server/envstore"
|
||||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
"github.com/authorizerdev/authorizer/server/sessionstore"
|
"github.com/authorizerdev/authorizer/server/sessionstore"
|
||||||
"github.com/authorizerdev/authorizer/server/token"
|
"github.com/authorizerdev/authorizer/server/token"
|
||||||
"github.com/authorizerdev/authorizer/server/utils"
|
"github.com/authorizerdev/authorizer/server/utils"
|
||||||
"golang.org/x/crypto/bcrypt"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// LoginResolver is a resolver for login mutation
|
// LoginResolver is a resolver for login mutation
|
||||||
func LoginResolver(ctx context.Context, params model.LoginInput) (*model.AuthResponse, error) {
|
func LoginResolver(ctx context.Context, params model.LoginInput) (*model.AuthResponse, error) {
|
||||||
gc, err := utils.GinContextFromContext(ctx)
|
|
||||||
var res *model.AuthResponse
|
var res *model.AuthResponse
|
||||||
|
|
||||||
|
gc, err := utils.GinContextFromContext(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to get GinContext: ", err)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableBasicAuthentication) {
|
if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableBasicAuthentication) {
|
||||||
|
log.Debug("Basic authentication is disabled.")
|
||||||
return res, fmt.Errorf(`basic authentication is disabled for this instance`)
|
return res, fmt.Errorf(`basic authentication is disabled for this instance`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log := log.WithFields(log.Fields{
|
||||||
|
"email": params.Email,
|
||||||
|
})
|
||||||
params.Email = strings.ToLower(params.Email)
|
params.Email = strings.ToLower(params.Email)
|
||||||
user, err := db.Provider.GetUserByEmail(params.Email)
|
user, err := db.Provider.GetUserByEmail(params.Email)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to get user by email: ", err)
|
||||||
return res, fmt.Errorf(`user with this email not found`)
|
return res, fmt.Errorf(`user with this email not found`)
|
||||||
}
|
}
|
||||||
|
|
||||||
if user.RevokedTimestamp != nil {
|
if user.RevokedTimestamp != nil {
|
||||||
|
log.Debug("User access is revoked")
|
||||||
return res, fmt.Errorf(`user access has been revoked`)
|
return res, fmt.Errorf(`user access has been revoked`)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !strings.Contains(user.SignupMethods, constants.SignupMethodBasicAuth) {
|
if !strings.Contains(user.SignupMethods, constants.SignupMethodBasicAuth) {
|
||||||
|
log.Debug("User signup method is not basic auth")
|
||||||
return res, fmt.Errorf(`user has not signed up email & password`)
|
return res, fmt.Errorf(`user has not signed up email & password`)
|
||||||
}
|
}
|
||||||
|
|
||||||
if user.EmailVerifiedAt == nil {
|
if user.EmailVerifiedAt == nil {
|
||||||
|
log.Debug("User email is not verified")
|
||||||
return res, fmt.Errorf(`email not verified`)
|
return res, fmt.Errorf(`email not verified`)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = bcrypt.CompareHashAndPassword([]byte(*user.Password), []byte(params.Password))
|
err = bcrypt.CompareHashAndPassword([]byte(*user.Password), []byte(params.Password))
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("compare password error:", err)
|
log.Debug("Failed to compare password: ", err)
|
||||||
return res, fmt.Errorf(`invalid password`)
|
return res, fmt.Errorf(`invalid password`)
|
||||||
}
|
}
|
||||||
roles := envstore.EnvStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyDefaultRoles)
|
roles := envstore.EnvStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyDefaultRoles)
|
||||||
currentRoles := strings.Split(user.Roles, ",")
|
currentRoles := strings.Split(user.Roles, ",")
|
||||||
if len(params.Roles) > 0 {
|
if len(params.Roles) > 0 {
|
||||||
if !utils.IsValidRoles(currentRoles, params.Roles) {
|
if !utils.IsValidRoles(params.Roles, currentRoles) {
|
||||||
|
log.Debug("Invalid roles: ", params.Roles)
|
||||||
return res, fmt.Errorf(`invalid roles`)
|
return res, fmt.Errorf(`invalid roles`)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,6 +84,7 @@ func LoginResolver(ctx context.Context, params model.LoginInput) (*model.AuthRes
|
|||||||
|
|
||||||
authToken, err := token.CreateAuthToken(gc, user, roles, scope)
|
authToken, err := token.CreateAuthToken(gc, user, roles, scope)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to create auth token", err)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,7 +110,11 @@ func LoginResolver(ctx context.Context, params model.LoginInput) (*model.AuthRes
|
|||||||
sessionstore.SetState(authToken.RefreshToken.Token, authToken.FingerPrint+"@"+user.ID)
|
sessionstore.SetState(authToken.RefreshToken.Token, authToken.FingerPrint+"@"+user.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
go utils.SaveSessionInDB(gc, user.ID)
|
go db.Provider.AddSession(models.Session{
|
||||||
|
UserID: user.ID,
|
||||||
|
UserAgent: utils.GetUserAgent(gc.Request),
|
||||||
|
IP: utils.GetIP(gc.Request),
|
||||||
|
})
|
||||||
|
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
@@ -3,6 +3,8 @@ package resolvers
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/cookie"
|
"github.com/authorizerdev/authorizer/server/cookie"
|
||||||
"github.com/authorizerdev/authorizer/server/crypto"
|
"github.com/authorizerdev/authorizer/server/crypto"
|
||||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
@@ -12,20 +14,24 @@ import (
|
|||||||
|
|
||||||
// LogoutResolver is a resolver for logout mutation
|
// LogoutResolver is a resolver for logout mutation
|
||||||
func LogoutResolver(ctx context.Context) (*model.Response, error) {
|
func LogoutResolver(ctx context.Context) (*model.Response, error) {
|
||||||
gc, err := utils.GinContextFromContext(ctx)
|
|
||||||
var res *model.Response
|
var res *model.Response
|
||||||
|
|
||||||
|
gc, err := utils.GinContextFromContext(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to get GinContext: ", err)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// get fingerprint hash
|
// get fingerprint hash
|
||||||
fingerprintHash, err := cookie.GetSession(gc)
|
fingerprintHash, err := cookie.GetSession(gc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to get fingerprint hash: ", err)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
decryptedFingerPrint, err := crypto.DecryptAES(fingerprintHash)
|
decryptedFingerPrint, err := crypto.DecryptAES(fingerprintHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to decrypt fingerprint hash: ", err)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -3,10 +3,11 @@ package resolvers
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/db"
|
"github.com/authorizerdev/authorizer/server/db"
|
||||||
"github.com/authorizerdev/authorizer/server/db/models"
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
@@ -20,21 +21,29 @@ import (
|
|||||||
// MagicLinkLoginResolver is a resolver for magic link login mutation
|
// MagicLinkLoginResolver is a resolver for magic link login mutation
|
||||||
func MagicLinkLoginResolver(ctx context.Context, params model.MagicLinkLoginInput) (*model.Response, error) {
|
func MagicLinkLoginResolver(ctx context.Context, params model.MagicLinkLoginInput) (*model.Response, error) {
|
||||||
var res *model.Response
|
var res *model.Response
|
||||||
|
|
||||||
gc, err := utils.GinContextFromContext(ctx)
|
gc, err := utils.GinContextFromContext(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to get GinContext: ", err)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableMagicLinkLogin) {
|
if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableMagicLinkLogin) {
|
||||||
|
log.Debug("Magic link login is disabled.")
|
||||||
return res, fmt.Errorf(`magic link login is disabled for this instance`)
|
return res, fmt.Errorf(`magic link login is disabled for this instance`)
|
||||||
}
|
}
|
||||||
|
|
||||||
params.Email = strings.ToLower(params.Email)
|
params.Email = strings.ToLower(params.Email)
|
||||||
|
|
||||||
if !utils.IsValidEmail(params.Email) {
|
if !utils.IsValidEmail(params.Email) {
|
||||||
|
log.Debug("Invalid email")
|
||||||
return res, fmt.Errorf(`invalid email address`)
|
return res, fmt.Errorf(`invalid email address`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log := log.WithFields(log.Fields{
|
||||||
|
"email": params.Email,
|
||||||
|
})
|
||||||
|
|
||||||
inputRoles := []string{}
|
inputRoles := []string{}
|
||||||
|
|
||||||
user := models.User{
|
user := models.User{
|
||||||
@@ -45,6 +54,7 @@ func MagicLinkLoginResolver(ctx context.Context, params model.MagicLinkLoginInpu
|
|||||||
existingUser, err := db.Provider.GetUserByEmail(params.Email)
|
existingUser, err := db.Provider.GetUserByEmail(params.Email)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableSignUp) {
|
if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableSignUp) {
|
||||||
|
log.Debug("Signup is disabled.")
|
||||||
return res, fmt.Errorf(`signup is disabled for this instance`)
|
return res, fmt.Errorf(`signup is disabled for this instance`)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,7 +62,8 @@ func MagicLinkLoginResolver(ctx context.Context, params model.MagicLinkLoginInpu
|
|||||||
// define roles for new user
|
// define roles for new user
|
||||||
if len(params.Roles) > 0 {
|
if len(params.Roles) > 0 {
|
||||||
// check if roles exists
|
// check if roles exists
|
||||||
if !utils.IsValidRoles(envstore.EnvStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyRoles), params.Roles) {
|
if !utils.IsValidRoles(params.Roles, envstore.EnvStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyRoles)) {
|
||||||
|
log.Debug("Invalid roles: ", params.Roles)
|
||||||
return res, fmt.Errorf(`invalid roles`)
|
return res, fmt.Errorf(`invalid roles`)
|
||||||
} else {
|
} else {
|
||||||
inputRoles = params.Roles
|
inputRoles = params.Roles
|
||||||
@@ -71,6 +82,7 @@ func MagicLinkLoginResolver(ctx context.Context, params model.MagicLinkLoginInpu
|
|||||||
// Need to modify roles in this case
|
// Need to modify roles in this case
|
||||||
|
|
||||||
if user.RevokedTimestamp != nil {
|
if user.RevokedTimestamp != nil {
|
||||||
|
log.Debug("User access is revoked at: ", user.RevokedTimestamp)
|
||||||
return res, fmt.Errorf(`user access has been revoked`)
|
return res, fmt.Errorf(`user access has been revoked`)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,6 +108,7 @@ func MagicLinkLoginResolver(ctx context.Context, params model.MagicLinkLoginInpu
|
|||||||
}
|
}
|
||||||
|
|
||||||
if hasProtectedRole {
|
if hasProtectedRole {
|
||||||
|
log.Debug("User is not assigned one of the protected roles", unasignedRoles)
|
||||||
return res, fmt.Errorf(`invalid roles`)
|
return res, fmt.Errorf(`invalid roles`)
|
||||||
} else {
|
} else {
|
||||||
user.Roles = existingUser.Roles + "," + strings.Join(unasignedRoles, ",")
|
user.Roles = existingUser.Roles + "," + strings.Join(unasignedRoles, ",")
|
||||||
@@ -112,7 +125,7 @@ func MagicLinkLoginResolver(ctx context.Context, params model.MagicLinkLoginInpu
|
|||||||
user.SignupMethods = signupMethod
|
user.SignupMethods = signupMethod
|
||||||
user, _ = db.Provider.UpdateUser(user)
|
user, _ = db.Provider.UpdateUser(user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error updating user:", err)
|
log.Debug("Failed to update user: ", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,6 +134,7 @@ func MagicLinkLoginResolver(ctx context.Context, params model.MagicLinkLoginInpu
|
|||||||
// insert verification request
|
// insert verification request
|
||||||
_, nonceHash, err := utils.GenerateNonce()
|
_, nonceHash, err := utils.GenerateNonce()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to generate nonce: ", err)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
redirectURLParams := "&roles=" + strings.Join(inputRoles, ",")
|
redirectURLParams := "&roles=" + strings.Join(inputRoles, ",")
|
||||||
@@ -144,7 +158,7 @@ func MagicLinkLoginResolver(ctx context.Context, params model.MagicLinkLoginInpu
|
|||||||
verificationType := constants.VerificationTypeMagicLinkLogin
|
verificationType := constants.VerificationTypeMagicLinkLogin
|
||||||
verificationToken, err := token.CreateVerificationToken(params.Email, verificationType, hostname, nonceHash, redirectURL)
|
verificationToken, err := token.CreateVerificationToken(params.Email, verificationType, hostname, nonceHash, redirectURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(`error generating token`, err)
|
log.Debug("Failed to create verification token: ", err)
|
||||||
}
|
}
|
||||||
_, err = db.Provider.AddVerificationRequest(models.VerificationRequest{
|
_, err = db.Provider.AddVerificationRequest(models.VerificationRequest{
|
||||||
Token: verificationToken,
|
Token: verificationToken,
|
||||||
@@ -155,6 +169,7 @@ func MagicLinkLoginResolver(ctx context.Context, params model.MagicLinkLoginInpu
|
|||||||
RedirectURI: redirectURL,
|
RedirectURI: redirectURL,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to add verification request in db: ", err)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -3,6 +3,8 @@ package resolvers
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/db"
|
"github.com/authorizerdev/authorizer/server/db"
|
||||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
"github.com/authorizerdev/authorizer/server/token"
|
"github.com/authorizerdev/authorizer/server/token"
|
||||||
@@ -11,25 +13,34 @@ import (
|
|||||||
|
|
||||||
// ProfileResolver is a resolver for profile query
|
// ProfileResolver is a resolver for profile query
|
||||||
func ProfileResolver(ctx context.Context) (*model.User, error) {
|
func ProfileResolver(ctx context.Context) (*model.User, error) {
|
||||||
gc, err := utils.GinContextFromContext(ctx)
|
|
||||||
var res *model.User
|
var res *model.User
|
||||||
|
|
||||||
|
gc, err := utils.GinContextFromContext(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to get GinContext: ", err)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
accessToken, err := token.GetAccessToken(gc)
|
accessToken, err := token.GetAccessToken(gc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to get access token: ", err)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
claims, err := token.ValidateAccessToken(gc, accessToken)
|
claims, err := token.ValidateAccessToken(gc, accessToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to validate access token: ", err)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
userID := claims["sub"].(string)
|
userID := claims["sub"].(string)
|
||||||
|
|
||||||
|
log := log.WithFields(log.Fields{
|
||||||
|
"user_id": userID,
|
||||||
|
})
|
||||||
user, err := db.Provider.GetUserByID(userID)
|
user, err := db.Provider.GetUserByID(userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to get user: ", err)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -3,10 +3,11 @@ package resolvers
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/db"
|
"github.com/authorizerdev/authorizer/server/db"
|
||||||
"github.com/authorizerdev/authorizer/server/db/models"
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
"github.com/authorizerdev/authorizer/server/email"
|
"github.com/authorizerdev/authorizer/server/email"
|
||||||
@@ -18,42 +19,48 @@ import (
|
|||||||
// ResendVerifyEmailResolver is a resolver for resend verify email mutation
|
// ResendVerifyEmailResolver is a resolver for resend verify email mutation
|
||||||
func ResendVerifyEmailResolver(ctx context.Context, params model.ResendVerifyEmailInput) (*model.Response, error) {
|
func ResendVerifyEmailResolver(ctx context.Context, params model.ResendVerifyEmailInput) (*model.Response, error) {
|
||||||
var res *model.Response
|
var res *model.Response
|
||||||
|
|
||||||
gc, err := utils.GinContextFromContext(ctx)
|
gc, err := utils.GinContextFromContext(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to get GinContext: ", err)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
params.Email = strings.ToLower(params.Email)
|
params.Email = strings.ToLower(params.Email)
|
||||||
|
|
||||||
if !utils.IsValidEmail(params.Email) {
|
if !utils.IsValidEmail(params.Email) {
|
||||||
|
log.Debug("Invalid email: ", params.Email)
|
||||||
return res, fmt.Errorf("invalid email")
|
return res, fmt.Errorf("invalid email")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !utils.IsValidVerificationIdentifier(params.Identifier) {
|
if !utils.IsValidVerificationIdentifier(params.Identifier) {
|
||||||
|
log.Debug("Invalid verification identifier: ", params.Identifier)
|
||||||
return res, fmt.Errorf("invalid identifier")
|
return res, fmt.Errorf("invalid identifier")
|
||||||
}
|
}
|
||||||
|
|
||||||
verificationRequest, err := db.Provider.GetVerificationRequestByEmail(params.Email, params.Identifier)
|
verificationRequest, err := db.Provider.GetVerificationRequestByEmail(params.Email, params.Identifier)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to get verification request: ", err)
|
||||||
return res, fmt.Errorf(`verification request not found`)
|
return res, fmt.Errorf(`verification request not found`)
|
||||||
}
|
}
|
||||||
|
|
||||||
// delete current verification and create new one
|
// delete current verification and create new one
|
||||||
err = db.Provider.DeleteVerificationRequest(verificationRequest)
|
err = db.Provider.DeleteVerificationRequest(verificationRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error deleting verification request:", err)
|
log.Debug("Failed to delete verification request: ", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
hostname := utils.GetHost(gc)
|
hostname := utils.GetHost(gc)
|
||||||
_, nonceHash, err := utils.GenerateNonce()
|
_, nonceHash, err := utils.GenerateNonce()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to generate nonce: ", err)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
verificationToken, err := token.CreateVerificationToken(params.Email, params.Identifier, hostname, nonceHash, verificationRequest.RedirectURI)
|
verificationToken, err := token.CreateVerificationToken(params.Email, params.Identifier, hostname, nonceHash, verificationRequest.RedirectURI)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(`error generating token`, err)
|
log.Debug("Failed to create verification token: ", err)
|
||||||
}
|
}
|
||||||
db.Provider.AddVerificationRequest(models.VerificationRequest{
|
_, err = db.Provider.AddVerificationRequest(models.VerificationRequest{
|
||||||
Token: verificationToken,
|
Token: verificationToken,
|
||||||
Identifier: params.Identifier,
|
Identifier: params.Identifier,
|
||||||
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
|
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
|
||||||
@@ -61,6 +68,9 @@ func ResendVerifyEmailResolver(ctx context.Context, params model.ResendVerifyEma
|
|||||||
Nonce: nonceHash,
|
Nonce: nonceHash,
|
||||||
RedirectURI: verificationRequest.RedirectURI,
|
RedirectURI: verificationRequest.RedirectURI,
|
||||||
})
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("Failed to add verification request: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
// exec it as go routin so that we can reduce the api latency
|
// exec it as go routin so that we can reduce the api latency
|
||||||
go email.SendVerificationMail(params.Email, verificationToken, hostname)
|
go email.SendVerificationMail(params.Email, verificationToken, hostname)
|
||||||
|
@@ -6,6 +6,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/crypto"
|
"github.com/authorizerdev/authorizer/server/crypto"
|
||||||
"github.com/authorizerdev/authorizer/server/db"
|
"github.com/authorizerdev/authorizer/server/db"
|
||||||
@@ -18,24 +20,30 @@ import (
|
|||||||
// ResetPasswordResolver is a resolver for reset password mutation
|
// ResetPasswordResolver is a resolver for reset password mutation
|
||||||
func ResetPasswordResolver(ctx context.Context, params model.ResetPasswordInput) (*model.Response, error) {
|
func ResetPasswordResolver(ctx context.Context, params model.ResetPasswordInput) (*model.Response, error) {
|
||||||
var res *model.Response
|
var res *model.Response
|
||||||
|
|
||||||
gc, err := utils.GinContextFromContext(ctx)
|
gc, err := utils.GinContextFromContext(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to get GinContext: ", err)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableBasicAuthentication) {
|
if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableBasicAuthentication) {
|
||||||
|
log.Debug("Basic authentication is disabled")
|
||||||
return res, fmt.Errorf(`basic authentication is disabled for this instance`)
|
return res, fmt.Errorf(`basic authentication is disabled for this instance`)
|
||||||
}
|
}
|
||||||
|
|
||||||
verificationRequest, err := db.Provider.GetVerificationRequestByToken(params.Token)
|
verificationRequest, err := db.Provider.GetVerificationRequestByToken(params.Token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to get verification request: ", err)
|
||||||
return res, fmt.Errorf(`invalid token`)
|
return res, fmt.Errorf(`invalid token`)
|
||||||
}
|
}
|
||||||
|
|
||||||
if params.Password != params.ConfirmPassword {
|
if params.Password != params.ConfirmPassword {
|
||||||
|
log.Debug("Passwords do not match")
|
||||||
return res, fmt.Errorf(`passwords don't match`)
|
return res, fmt.Errorf(`passwords don't match`)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !utils.IsValidPassword(params.Password) {
|
if !utils.IsValidPassword(params.Password) {
|
||||||
|
log.Debug("Invalid password")
|
||||||
return res, fmt.Errorf(`password is not valid. It needs to be at least 6 characters long and contain at least one number, one uppercase letter, one lowercase letter and one special character`)
|
return res, fmt.Errorf(`password is not valid. It needs to be at least 6 characters long and contain at least one number, one uppercase letter, one lowercase letter and one special character`)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,11 +51,17 @@ func ResetPasswordResolver(ctx context.Context, params model.ResetPasswordInput)
|
|||||||
hostname := utils.GetHost(gc)
|
hostname := utils.GetHost(gc)
|
||||||
claim, err := token.ParseJWTToken(params.Token, hostname, verificationRequest.Nonce, verificationRequest.Email)
|
claim, err := token.ParseJWTToken(params.Token, hostname, verificationRequest.Nonce, verificationRequest.Email)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to parse token: ", err)
|
||||||
return res, fmt.Errorf(`invalid token`)
|
return res, fmt.Errorf(`invalid token`)
|
||||||
}
|
}
|
||||||
|
|
||||||
user, err := db.Provider.GetUserByEmail(claim["sub"].(string))
|
email := claim["sub"].(string)
|
||||||
|
log := log.WithFields(log.Fields{
|
||||||
|
"email": email,
|
||||||
|
})
|
||||||
|
user, err := db.Provider.GetUserByEmail(email)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to get user: ", err)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,8 +81,17 @@ func ResetPasswordResolver(ctx context.Context, params model.ResetPasswordInput)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// delete from verification table
|
// delete from verification table
|
||||||
db.Provider.DeleteVerificationRequest(verificationRequest)
|
err = db.Provider.DeleteVerificationRequest(verificationRequest)
|
||||||
db.Provider.UpdateUser(user)
|
if err != nil {
|
||||||
|
log.Debug("Failed to delete verification request: ", err)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = db.Provider.UpdateUser(user)
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("Failed to update user: ", err)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
res = &model.Response{
|
res = &model.Response{
|
||||||
Message: `Password updated successfully.`,
|
Message: `Password updated successfully.`,
|
||||||
|
@@ -3,9 +3,10 @@ package resolvers
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/db"
|
"github.com/authorizerdev/authorizer/server/db"
|
||||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
"github.com/authorizerdev/authorizer/server/sessionstore"
|
"github.com/authorizerdev/authorizer/server/sessionstore"
|
||||||
@@ -15,18 +16,25 @@ import (
|
|||||||
|
|
||||||
// RevokeAccessResolver is a resolver for revoking user access
|
// RevokeAccessResolver is a resolver for revoking user access
|
||||||
func RevokeAccessResolver(ctx context.Context, params model.UpdateAccessInput) (*model.Response, error) {
|
func RevokeAccessResolver(ctx context.Context, params model.UpdateAccessInput) (*model.Response, error) {
|
||||||
gc, err := utils.GinContextFromContext(ctx)
|
|
||||||
var res *model.Response
|
var res *model.Response
|
||||||
|
|
||||||
|
gc, err := utils.GinContextFromContext(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to get GinContext: ", err)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !token.IsSuperAdmin(gc) {
|
if !token.IsSuperAdmin(gc) {
|
||||||
|
log.Debug("Not logged in as super admin")
|
||||||
return res, fmt.Errorf("unauthorized")
|
return res, fmt.Errorf("unauthorized")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log := log.WithFields(log.Fields{
|
||||||
|
"user_id": params.UserID,
|
||||||
|
})
|
||||||
user, err := db.Provider.GetUserByID(params.UserID)
|
user, err := db.Provider.GetUserByID(params.UserID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to get user by ID: ", err)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,7 +43,7 @@ func RevokeAccessResolver(ctx context.Context, params model.UpdateAccessInput) (
|
|||||||
|
|
||||||
user, err = db.Provider.UpdateUser(user)
|
user, err = db.Provider.UpdateUser(user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error updating user:", err)
|
log.Debug("Failed to update user: ", err)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -4,9 +4,10 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/cookie"
|
"github.com/authorizerdev/authorizer/server/cookie"
|
||||||
"github.com/authorizerdev/authorizer/server/db"
|
"github.com/authorizerdev/authorizer/server/db"
|
||||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||||
@@ -22,22 +23,28 @@ func SessionResolver(ctx context.Context, params *model.SessionQueryInput) (*mod
|
|||||||
|
|
||||||
gc, err := utils.GinContextFromContext(ctx)
|
gc, err := utils.GinContextFromContext(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to get GinContext: ", err)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
sessionToken, err := cookie.GetSession(gc)
|
sessionToken, err := cookie.GetSession(gc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error getting session token:", err)
|
log.Debug("Failed to get session token", err)
|
||||||
return res, errors.New("unauthorized")
|
return res, errors.New("unauthorized")
|
||||||
}
|
}
|
||||||
|
|
||||||
// get session from cookie
|
// get session from cookie
|
||||||
claims, err := token.ValidateBrowserSession(gc, sessionToken)
|
claims, err := token.ValidateBrowserSession(gc, sessionToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("session validation failed:", err)
|
log.Debug("Failed to validate session token", err)
|
||||||
return res, errors.New("unauthorized")
|
return res, errors.New("unauthorized")
|
||||||
}
|
}
|
||||||
userID := claims.Subject
|
userID := claims.Subject
|
||||||
|
|
||||||
|
log := log.WithFields(log.Fields{
|
||||||
|
"user_id": userID,
|
||||||
|
})
|
||||||
|
|
||||||
user, err := db.Provider.GetUserByID(userID)
|
user, err := db.Provider.GetUserByID(userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return res, err
|
return res, err
|
||||||
@@ -46,13 +53,12 @@ func SessionResolver(ctx context.Context, params *model.SessionQueryInput) (*mod
|
|||||||
// refresh token has "roles" as claim
|
// refresh token has "roles" as claim
|
||||||
claimRoleInterface := claims.Roles
|
claimRoleInterface := claims.Roles
|
||||||
claimRoles := []string{}
|
claimRoles := []string{}
|
||||||
for _, v := range claimRoleInterface {
|
claimRoles = append(claimRoles, claimRoleInterface...)
|
||||||
claimRoles = append(claimRoles, v)
|
|
||||||
}
|
|
||||||
|
|
||||||
if params != nil && params.Roles != nil && len(params.Roles) > 0 {
|
if params != nil && params.Roles != nil && len(params.Roles) > 0 {
|
||||||
for _, v := range params.Roles {
|
for _, v := range params.Roles {
|
||||||
if !utils.StringSliceContains(claimRoles, v) {
|
if !utils.StringSliceContains(claimRoles, v) {
|
||||||
|
log.Debug("User does not have required role: ", claimRoles, v)
|
||||||
return res, fmt.Errorf(`unauthorized`)
|
return res, fmt.Errorf(`unauthorized`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -65,6 +71,7 @@ func SessionResolver(ctx context.Context, params *model.SessionQueryInput) (*mod
|
|||||||
|
|
||||||
authToken, err := token.CreateAuthToken(gc, user, claimRoles, scope)
|
authToken, err := token.CreateAuthToken(gc, user, claimRoles, scope)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to create auth token: ", err)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -3,10 +3,11 @@ package resolvers
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
"github.com/authorizerdev/authorizer/server/cookie"
|
"github.com/authorizerdev/authorizer/server/cookie"
|
||||||
"github.com/authorizerdev/authorizer/server/crypto"
|
"github.com/authorizerdev/authorizer/server/crypto"
|
||||||
@@ -22,44 +23,56 @@ import (
|
|||||||
|
|
||||||
// SignupResolver is a resolver for signup mutation
|
// SignupResolver is a resolver for signup mutation
|
||||||
func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthResponse, error) {
|
func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthResponse, error) {
|
||||||
gc, err := utils.GinContextFromContext(ctx)
|
|
||||||
var res *model.AuthResponse
|
var res *model.AuthResponse
|
||||||
|
|
||||||
|
gc, err := utils.GinContextFromContext(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to get GinContext: ", err)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableSignUp) {
|
if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableSignUp) {
|
||||||
|
log.Debug("Signup is disabled")
|
||||||
return res, fmt.Errorf(`signup is disabled for this instance`)
|
return res, fmt.Errorf(`signup is disabled for this instance`)
|
||||||
}
|
}
|
||||||
|
|
||||||
if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableBasicAuthentication) {
|
if envstore.EnvStoreObj.GetBoolStoreEnvVariable(constants.EnvKeyDisableBasicAuthentication) {
|
||||||
|
log.Debug("Basic authentication is disabled")
|
||||||
return res, fmt.Errorf(`basic authentication is disabled for this instance`)
|
return res, fmt.Errorf(`basic authentication is disabled for this instance`)
|
||||||
}
|
}
|
||||||
|
|
||||||
if params.ConfirmPassword != params.Password {
|
if params.ConfirmPassword != params.Password {
|
||||||
|
log.Debug("Passwords do not match")
|
||||||
return res, fmt.Errorf(`password and confirm password does not match`)
|
return res, fmt.Errorf(`password and confirm password does not match`)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !utils.IsValidPassword(params.Password) {
|
if !utils.IsValidPassword(params.Password) {
|
||||||
|
log.Debug("Invalid password")
|
||||||
return res, fmt.Errorf(`password is not valid. It needs to be at least 6 characters long and contain at least one number, one uppercase letter, one lowercase letter and one special character`)
|
return res, fmt.Errorf(`password is not valid. It needs to be at least 6 characters long and contain at least one number, one uppercase letter, one lowercase letter and one special character`)
|
||||||
}
|
}
|
||||||
|
|
||||||
params.Email = strings.ToLower(params.Email)
|
params.Email = strings.ToLower(params.Email)
|
||||||
|
|
||||||
if !utils.IsValidEmail(params.Email) {
|
if !utils.IsValidEmail(params.Email) {
|
||||||
|
log.Debug("Invalid email: ", params.Email)
|
||||||
return res, fmt.Errorf(`invalid email address`)
|
return res, fmt.Errorf(`invalid email address`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log := log.WithFields(log.Fields{
|
||||||
|
"email": params.Email,
|
||||||
|
})
|
||||||
// find user with email
|
// find user with email
|
||||||
existingUser, err := db.Provider.GetUserByEmail(params.Email)
|
existingUser, err := db.Provider.GetUserByEmail(params.Email)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("user with email " + params.Email + " not found")
|
log.Debug("Failed to get user by email: ", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if existingUser.EmailVerifiedAt != nil {
|
if existingUser.EmailVerifiedAt != nil {
|
||||||
// email is verified
|
// email is verified
|
||||||
|
log.Debug("Email is already verified and signed up.")
|
||||||
return res, fmt.Errorf(`%s has already signed up`, params.Email)
|
return res, fmt.Errorf(`%s has already signed up`, params.Email)
|
||||||
} else if existingUser.ID != "" && existingUser.EmailVerifiedAt == nil {
|
} else if existingUser.ID != "" && existingUser.EmailVerifiedAt == nil {
|
||||||
|
log.Debug("Email is already signed up. Verification pending...")
|
||||||
return res, fmt.Errorf("%s has already signed up. please complete the email verification process or reset the password", params.Email)
|
return res, fmt.Errorf("%s has already signed up. please complete the email verification process or reset the password", params.Email)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,6 +81,7 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR
|
|||||||
if len(params.Roles) > 0 {
|
if len(params.Roles) > 0 {
|
||||||
// check if roles exists
|
// check if roles exists
|
||||||
if !utils.IsValidRoles(envstore.EnvStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyRoles), params.Roles) {
|
if !utils.IsValidRoles(envstore.EnvStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyRoles), params.Roles) {
|
||||||
|
log.Debug("Invalid roles: ", params.Roles)
|
||||||
return res, fmt.Errorf(`invalid roles`)
|
return res, fmt.Errorf(`invalid roles`)
|
||||||
} else {
|
} else {
|
||||||
inputRoles = params.Roles
|
inputRoles = params.Roles
|
||||||
@@ -124,6 +138,7 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR
|
|||||||
}
|
}
|
||||||
user, err = db.Provider.AddUser(user)
|
user, err = db.Provider.AddUser(user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to add user: ", err)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
roles := strings.Split(user.Roles, ",")
|
roles := strings.Split(user.Roles, ",")
|
||||||
@@ -134,6 +149,7 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR
|
|||||||
// insert verification request
|
// insert verification request
|
||||||
_, nonceHash, err := utils.GenerateNonce()
|
_, nonceHash, err := utils.GenerateNonce()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to generate nonce: ", err)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
verificationType := constants.VerificationTypeBasicAuthSignup
|
verificationType := constants.VerificationTypeBasicAuthSignup
|
||||||
@@ -143,9 +159,10 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR
|
|||||||
}
|
}
|
||||||
verificationToken, err := token.CreateVerificationToken(params.Email, verificationType, hostname, nonceHash, redirectURL)
|
verificationToken, err := token.CreateVerificationToken(params.Email, verificationType, hostname, nonceHash, redirectURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to create verification token: ", err)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
db.Provider.AddVerificationRequest(models.VerificationRequest{
|
_, err = db.Provider.AddVerificationRequest(models.VerificationRequest{
|
||||||
Token: verificationToken,
|
Token: verificationToken,
|
||||||
Identifier: verificationType,
|
Identifier: verificationType,
|
||||||
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
|
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
|
||||||
@@ -153,6 +170,10 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR
|
|||||||
Nonce: nonceHash,
|
Nonce: nonceHash,
|
||||||
RedirectURI: redirectURL,
|
RedirectURI: redirectURL,
|
||||||
})
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("Failed to add verification request: ", err)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
// exec it as go routin so that we can reduce the api latency
|
// exec it as go routin so that we can reduce the api latency
|
||||||
go email.SendVerificationMail(params.Email, verificationToken, hostname)
|
go email.SendVerificationMail(params.Email, verificationToken, hostname)
|
||||||
@@ -169,12 +190,17 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR
|
|||||||
|
|
||||||
authToken, err := token.CreateAuthToken(gc, user, roles, scope)
|
authToken, err := token.CreateAuthToken(gc, user, roles, scope)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Debug("Failed to create auth token: ", err)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
sessionstore.SetState(authToken.FingerPrintHash, authToken.FingerPrint+"@"+user.ID)
|
sessionstore.SetState(authToken.FingerPrintHash, authToken.FingerPrint+"@"+user.ID)
|
||||||
cookie.SetSession(gc, authToken.FingerPrintHash)
|
cookie.SetSession(gc, authToken.FingerPrintHash)
|
||||||
go utils.SaveSessionInDB(gc, user.ID)
|
go db.Provider.AddSession(models.Session{
|
||||||
|
UserID: user.ID,
|
||||||
|
UserAgent: utils.GetUserAgent(gc.Request),
|
||||||
|
IP: utils.GetIP(gc.Request),
|
||||||
|
})
|
||||||
|
|
||||||
expiresIn := authToken.AccessToken.ExpiresAt - time.Now().Unix()
|
expiresIn := authToken.AccessToken.ExpiresAt - time.Now().Unix()
|
||||||
if expiresIn <= 0 {
|
if expiresIn <= 0 {
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user