Compare commits

..

23 Commits

Author SHA1 Message Date
Lakhan Samani
27160ecbd5 chore: fix arm dependencies 2022-11-09 09:46:27 +05:30
Lakhan Samani
c6c3af1114 chore: update dependencies for cross compile 2022-11-09 04:31:04 +05:30
Lakhan Samani
e54b7f18f0 chore: add dependencies for cross compile 2022-11-09 04:25:15 +05:30
Lakhan Samani
a18046748b chore: add cgo param to gox 2022-11-09 04:09:55 +05:30
Lakhan Samani
1bff6720fc chore: install gox 2022-11-09 03:59:20 +05:30
Lakhan Samani
024ffd85f3 chore: fix yaml indentation 2022-11-09 03:52:47 +05:30
Lakhan Samani
e171820614 chore: use checkout@v3 2022-11-09 03:51:08 +05:30
Lakhan Samani
19f9caf478 chore: test gox + buildx 2022-11-09 03:47:28 +05:30
Lakhan Samani
4afd544c41 feat(server): add allowed_roles in access_token + refresh_token 2022-11-07 07:11:23 +05:30
Lakhan Samani
307c6f7d15 fix: refresh token login method claim 2022-11-04 01:40:18 +05:30
Lakhan Samani
bbc6394cf3 Merge pull request #286 from Pjort/main
fixed validation of refresh token
2022-11-03 20:10:40 +05:30
Pjort Kat
63c8e2e55f fixed validation of refresh token 2022-11-03 11:51:59 +01:00
Lakhan Samani
b224892a39 fix: minor space 2022-11-02 08:48:56 +05:30
Lakhan Samani
13edf1965c Merge pull request #285 from authorizerdev/development
feat(server): add jwt claims as part of validation endpoint
2022-11-01 10:15:08 +05:30
Lakhan Samani
1f220a5205 add jwt claims as part of validation endpoint 2022-11-01 10:12:01 +05:30
Lakhan Samani
32fb954a1c Merge pull request #281 from authorizerdev/development
chore: 1.1.22-rc.0
2022-10-25 08:27:02 +05:30
Lakhan Samani
65eadb66fa chore: format 2022-10-25 08:25:23 +05:30
Lakhan Samani
9ce53eb8e8 Merge branch 'development' of https://github.com/authorizerdev/authorizer into development 2022-10-25 08:21:32 +05:30
Lakhan Samani
3b196f074b Merge pull request #280 from authorizerdev/feat/user-roles-multi-select
feat: add user roles multi select input
2022-10-25 08:19:08 +05:30
Lakhan Samani
f2fe584793 feat: add support for SMTP LocalName
Resolves #274
2022-10-25 08:18:29 +05:30
Lakhan Samani
287b952dad fix: forgot password redirect from app 2022-10-24 11:37:42 +05:30
Lakhan Samani
e690066652 fix(server):give higher preference to redirect_uri
While using forgot_password redirect URI was ignored if not present

Resolves #275
2022-10-24 11:15:36 +05:30
anik-ghosh-au7
0f67d74657 feat: add user roles multi select input 2022-10-23 22:59:17 +05:30
26 changed files with 410 additions and 89 deletions

View File

@@ -2,36 +2,45 @@ on:
workflow_dispatch:
inputs:
logLevel:
description: 'Log level'
description: "Log level"
required: true
default: 'warning'
default: "warning"
type: choice
options:
- info
- warning
- debug
- info
- warning
- debug
tags:
description: 'Tags'
required: false
description: "Tags"
required: false
type: boolean
release:
types: [created]
jobs:
releases:
name: Release Authorizer Binary
name: Release Authorizer
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- uses: actions/setup-node@v2
with:
node-version: '16'
node-version: "16"
- # Add support for more platforms with QEMU (optional)
# https://github.com/docker/setup-qemu-action
name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
with:
platforms: linux/amd64,linux/arm64
buildkitd-flags: --debug
- uses: actions/setup-go@v2
with:
go-version: '^1.17.3'
go-version: "^1.17.3"
- name: Install dependencies
run: |
sudo apt-get install build-essential wget zip gcc-mingw-w64 && \
sudo apt-get install build-essential wget zip gcc-mingw-w64 gcc-9-aarch64-linux-gnu gcc-aarch64-linux-gnu libc6-dev-arm64-cross && \
echo "/usr/bin/x86_64-w64-mingw32-gcc" >> GITHUB_PATH && \
wget --no-check-certificate --progress=dot:mega https://github.com/wangyoucao577/assets-uploader/releases/download/v0.3.0/github-assets-uploader-v0.3.0-linux-amd64.tar.gz -O github-assets-uploader.tar.gz && \
tar -zxf github-assets-uploader.tar.gz && \
@@ -44,25 +53,20 @@ jobs:
run: whereis go
- name: Print Go Version
run: go version
- name: Install gox
run: go install github.com/mitchellh/gox@latest
- name: Set VERSION env
run: echo VERSION=$(basename ${GITHUB_REF}) >> ${GITHUB_ENV}
- name: Copy .env file
run: mv .env.sample .env
- name: Package files for windows
- name: Build package
run: |
make clean && \
CGO_ENABLED=1 GOOS=windows CC=/usr/bin/x86_64-w64-mingw32-gcc make && \
mv build/server build/server.exe && \
zip -vr authorizer-${VERSION}-windows-amd64.zip .env app/build build templates dashboard/build
- name: Package files for linux
run: |
make clean && \
CGO_ENABLED=1 make && \
tar cvfz authorizer-${VERSION}-linux-amd64.tar.gz .env app/build build templates dashboard/build
make build && \
mkdir -p authorizer-${VERSION}-darwin-amd64/build authorizer-${VERSION}-darwin-amd64/app authorizer-${VERSION}-darwin-amd64/templates authorizer-${VERSION}-darwin-amd64/dashboard && cp build/darwin/amd64/server authorizer-${VERSION}-darwin-amd64/build/ && cp .env authorizer-${VERSION}-darwin-amd64/.env && cp -rf app/build authorizer-${VERSION}-darwin-amd64/app/build && cp -rf templates authorizer-${VERSION}-darwin-amd64/templates && cp -rf dashboard/build authorizer-${VERSION}-darwin-amd64/dashboard/build && tar cvfz authorizer-${VERSION}-darwin-amd64.tar.gz authorizer-${VERSION}-darwin-amd64
- name: Upload assets
run: |
github-assets-uploader -f authorizer-${VERSION}-windows-amd64.zip -mediatype application/zip -repo authorizerdev/authorizer -token ${{secrets.RELEASE_TOKEN}} -tag ${VERSION} && \
github-assets-uploader -f authorizer-${VERSION}-linux-amd64.tar.gz -mediatype application/gzip -repo authorizerdev/authorizer -token ${{secrets.RELEASE_TOKEN}} -tag ${VERSION}
github-assets-uploader -f authorizer-${VERSION}-darwin-amd64.tar.gz -mediatype application/gzip -repo authorizerdev/authorizer -token ${{secrets.RELEASE_TOKEN}} -tag ${VERSION}
- name: Log in to Docker Hub
uses: docker/login-action@v1
with:
@@ -74,6 +78,9 @@ jobs:
uses: docker/metadata-action@v3
with:
images: lakhansamani/authorizer
tags: |
# set latest tag for default branch
type=raw,value=latest,enable={{is_default_branch}}
- name: Build and push Docker image
uses: docker/build-push-action@v2

View File

@@ -3,6 +3,12 @@ VERSION := $(or $(VERSION),$(DEFAULT_VERSION))
cmd:
cd server && go build -ldflags "-w -X main.VERSION=$(VERSION)" -o '../build/server'
build:
cd server && gox -cgo \
-osarch="linux/amd64 linux/arm64 darwin/amd64 windows/386 windows/amd64" \
-ldflags "-w -X main.VERSION=$(VERSION)" \
-output="../build/{{.OS}}/{{.Arch}}/server" \
./...
build-app:
cd app && npm i && npm run build
build-dashboard:

View File

@@ -60,7 +60,12 @@ export default function Login({ urlProps }: { urlProps: Record<string, any> }) {
{view === VIEW_TYPES.FORGOT_PASSWORD && (
<Fragment>
<h1 style={{ textAlign: 'center' }}>Forgot Password</h1>
<AuthorizerForgotPassword urlProps={urlProps} />
<AuthorizerForgotPassword
urlProps={{
...urlProps,
redirect_uri: `${window.location.origin}/app/reset-password`,
}}
/>
<Footer>
<Link
to="#"

View File

@@ -1,4 +1,4 @@
import React from 'react';
import React, { useState } from 'react';
import {
Button,
Center,
@@ -20,13 +20,14 @@ import { useClient } from 'urql';
import { FaSave } from 'react-icons/fa';
import InputField from './InputField';
import {
ArrayInputType,
DateInputType,
MultiSelectInputType,
SelectInputType,
TextInputType,
} from '../constants';
import { getObjectDiff } from '../utils';
import { UpdateUser } from '../graphql/mutation';
import { GetAvailableRolesQuery } from '../graphql/queries';
const GenderTypes = {
Undisclosed: null,
@@ -57,8 +58,9 @@ const EditUserModal = ({
}) => {
const client = useClient();
const toast = useToast();
const [availableRoles, setAvailableRoles] = useState<string[]>([]);
const { isOpen, onOpen, onClose } = useDisclosure();
const [userData, setUserData] = React.useState<userDataTypes>({
const [userData, setUserData] = useState<userDataTypes>({
id: '',
email: '',
given_name: '',
@@ -73,7 +75,17 @@ const EditUserModal = ({
});
React.useEffect(() => {
setUserData(user);
fetchAvailableRoles();
}, []);
const fetchAvailableRoles = async () => {
const res = await client.query(GetAvailableRolesQuery).toPromise();
if (res.data?._env?.ROLES && res.data?._env?.PROTECTED_ROLES) {
setAvailableRoles([
...res.data._env.ROLES,
...res.data._env.PROTECTED_ROLES,
]);
}
};
const saveHandler = async () => {
const diff = getObjectDiff(user, userData);
const updatedUserData = diff.reduce(
@@ -221,7 +233,8 @@ const EditUserModal = ({
<InputField
variables={userData}
setVariables={setUserData}
inputType={ArrayInputType.USER_ROLES}
availableRoles={availableRoles}
inputType={MultiSelectInputType.USER_ROLES}
/>
</Center>
</Flex>

View File

@@ -48,6 +48,26 @@ const EmailConfigurations = ({
/>
</Center>
</Flex>
<Flex direction={isNotSmallerScreen ? 'row' : 'column'}>
<Flex
w={isNotSmallerScreen ? '30%' : '40%'}
justifyContent="start"
alignItems="center"
>
<Text fontSize="sm">SMTP Local Name:</Text>
</Flex>
<Center
w={isNotSmallerScreen ? '70%' : '100%'}
mt={isNotSmallerScreen ? '0' : '3'}
>
<InputField
borderRadius={5}
variables={variables}
setVariables={setVariables}
inputType={TextInputType.SMTP_LOCAL_NAME}
/>
</Center>
</Flex>
<Flex direction={isNotSmallerScreen ? 'row' : 'column'}>
<Flex
w={isNotSmallerScreen ? '30%' : '40%'}

View File

@@ -1,4 +1,4 @@
import React from 'react';
import React, { useState } from 'react';
import {
Box,
Flex,
@@ -13,6 +13,12 @@ import {
Textarea,
Switch,
Text,
MenuButton,
MenuList,
MenuItemOption,
MenuOptionGroup,
Button,
Menu,
} from '@chakra-ui/react';
import {
FaRegClone,
@@ -20,6 +26,7 @@ import {
FaRegEyeSlash,
FaPlus,
FaTimes,
FaAngleDown,
} from 'react-icons/fa';
import {
ArrayInputOperations,
@@ -30,6 +37,7 @@ import {
TextAreaInputType,
SwitchInputType,
DateInputType,
MultiSelectInputType,
} from '../constants';
import { copyTextToClipboard } from '../utils';
@@ -39,13 +47,16 @@ const InputField = ({
setVariables,
fieldVisibility,
setFieldVisibility,
availableRoles,
...downshiftProps
}: any) => {
const props = {
size: 'sm',
...downshiftProps,
};
const [inputFieldVisibility, setInputFieldVisibility] = React.useState<
const [availableUserRoles, setAvailableUserRoles] =
useState<string[]>(availableRoles);
const [inputFieldVisibility, setInputFieldVisibility] = useState<
Record<string, boolean>
>({
ROLES: false,
@@ -54,7 +65,7 @@ const InputField = ({
ALLOWED_ORIGINS: false,
roles: false,
});
const [inputData, setInputData] = React.useState<Record<string, string>>({
const [inputData, setInputData] = useState<Record<string, string>>({
ROLES: '',
DEFAULT_ROLES: '',
PROTECTED_ROLES: '',
@@ -116,7 +127,7 @@ const InputField = ({
<InputGroup size="sm">
<Input
{...props}
value={variables[inputType] ?? ''}
value={variables[inputType] || ''}
onChange={(
event: Event & {
target: HTMLInputElement;
@@ -221,7 +232,7 @@ const InputField = ({
size="xs"
minW="150px"
placeholder="add a new value"
value={inputData[inputType] ?? ''}
value={inputData[inputType] || ''}
onChange={(e: any) => {
setInputData({ ...inputData, [inputType]: e.target.value });
}}
@@ -278,6 +289,87 @@ const InputField = ({
</Select>
);
}
if (Object.values(MultiSelectInputType).includes(inputType)) {
return (
<Flex w="100%" style={{ position: 'relative' }}>
<Flex
border="1px solid #e2e8f0"
w="100%"
borderRadius="var(--chakra-radii-sm)"
p="1% 0 0 2.5%"
overflowX={variables[inputType].length > 3 ? 'scroll' : 'hidden'}
overflowY="hidden"
justifyContent="space-between"
alignItems="center"
>
<Flex justifyContent="start" alignItems="center" w="100%" wrap="wrap">
{variables[inputType].map((role: string, index: number) => (
<Box key={index} margin="0.5%" role="group">
<Tag
size="sm"
variant="outline"
colorScheme="gray"
minW="fit-content"
>
<TagLabel cursor="default">{role}</TagLabel>
<TagRightIcon
boxSize="12px"
as={FaTimes}
display="none"
cursor="pointer"
_groupHover={{ display: 'block' }}
onClick={() =>
updateInputHandler(
inputType,
ArrayInputOperations.REMOVE,
role,
)
}
/>
</Tag>
</Box>
))}
</Flex>
<Menu matchWidth={true}>
<MenuButton px="10px" py="7.5px">
<FaAngleDown />
</MenuButton>
<MenuList
position="absolute"
top="0"
right="0"
zIndex="10"
maxH="150"
overflowX="scroll"
>
<MenuOptionGroup
title={undefined}
value={variables[inputType]}
type="checkbox"
onChange={(values: string[] | string) => {
setVariables({
...variables,
[inputType]: values,
});
}}
>
{availableUserRoles.map((role) => {
return (
<MenuItemOption
key={`multiselect-menu-${role}`}
value={role}
>
{role}
</MenuItemOption>
);
})}
</MenuOptionGroup>
</MenuList>
</Menu>
</Flex>
</Flex>
);
}
if (Object.values(TextAreaInputType).includes(inputType)) {
return (
<Textarea

View File

@@ -15,6 +15,7 @@ export const TextInputType = {
SMTP_HOST: 'SMTP_HOST',
SMTP_PORT: 'SMTP_PORT',
SMTP_USERNAME: 'SMTP_USERNAME',
SMTP_LOCAL_NAME: 'SMTP_LOCAL_NAME',
SENDER_EMAIL: 'SENDER_EMAIL',
ORGANIZATION_NAME: 'ORGANIZATION_NAME',
ORGANIZATION_LOGO: 'ORGANIZATION_LOGO',
@@ -48,7 +49,6 @@ export const ArrayInputType = {
DEFAULT_ROLES: 'DEFAULT_ROLES',
PROTECTED_ROLES: 'PROTECTED_ROLES',
ALLOWED_ORIGINS: 'ALLOWED_ORIGINS',
USER_ROLES: 'roles',
};
export const SelectInputType = {
@@ -56,6 +56,10 @@ export const SelectInputType = {
GENDER: 'gender',
};
export const MultiSelectInputType = {
USER_ROLES: 'roles',
};
export const TextAreaInputType = {
CUSTOM_ACCESS_TOKEN_SCRIPT: 'CUSTOM_ACCESS_TOKEN_SCRIPT',
JWT_PRIVATE_KEY: 'JWT_PRIVATE_KEY',
@@ -129,6 +133,7 @@ export interface envVarTypes {
SMTP_PORT: string;
SMTP_USERNAME: string;
SMTP_PASSWORD: string;
SMTP_LOCAL_NAME: string;
SENDER_EMAIL: string;
ALLOWED_ORIGINS: [string] | [];
ORGANIZATION_NAME: string;

View File

@@ -45,6 +45,7 @@ export const EnvVariablesQuery = `
SMTP_PORT
SMTP_USERNAME
SMTP_PASSWORD
SMTP_LOCAL_NAME
SENDER_EMAIL
ALLOWED_ORIGINS
ORGANIZATION_NAME
@@ -169,3 +170,12 @@ export const WebhookLogsQuery = `
}
}
`;
export const GetAvailableRolesQuery = `
query {
_env {
ROLES
PROTECTED_ROLES
}
}
`;

View File

@@ -65,6 +65,7 @@ const Environment = () => {
SMTP_PORT: '',
SMTP_USERNAME: '',
SMTP_PASSWORD: '',
SMTP_LOCAL_NAME: '',
SENDER_EMAIL: '',
ALLOWED_ORIGINS: [],
ORGANIZATION_NAME: '',

View File

@@ -51,6 +51,8 @@ const (
EnvKeySmtpUsername = "SMTP_USERNAME"
// EnvKeySmtpPassword key for env variable SMTP_PASSWORD
EnvKeySmtpPassword = "SMTP_PASSWORD"
// EnvKeySmtpLocalName key for env variable SMTP_LOCAL_NAME
EnvKeySmtpLocalName = "SMTP_LOCAL_NAME"
// EnvKeySenderEmail key for env variable SENDER_EMAIL
EnvKeySenderEmail = "SENDER_EMAIL"
// EnvKeyIsEmailServiceEnabled key for env variable IS_EMAIL_SERVICE_ENABLED

View File

@@ -26,7 +26,6 @@ func NewProvider() (*provider, error) {
config := aws.Config{
MaxRetries: aws.Int(3),
CredentialsChainVerboseErrors: aws.Bool(true), // for full error logs
}
if awsRegion != "" {

View File

@@ -5,6 +5,7 @@ import (
"context"
"crypto/tls"
"strconv"
"strings"
"text/template"
log "github.com/sirupsen/logrus"
@@ -126,6 +127,12 @@ func SendEmail(to []string, event string, data map[string]interface{}) error {
return err
}
smtpLocalName, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeySmtpLocalName)
if err != nil {
log.Debugf("Error while getting smtp localname from env variable: %v", err)
smtpLocalName = ""
}
isProd, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyIsProd)
if err != nil {
log.Errorf("Error while getting env variable: %v", err)
@@ -141,6 +148,11 @@ func SendEmail(to []string, event string, data map[string]interface{}) error {
if !isProd {
d.TLSConfig = &tls.Config{InsecureSkipVerify: true}
}
if strings.TrimSpace(smtpLocalName) != "" {
d.LocalName = smtpLocalName
}
if err := d.DialAndSend(m); err != nil {
log.Debug("SMTP Failed: ", err)
return err

8
server/env/env.go vendored
View File

@@ -55,6 +55,7 @@ func InitAllEnv() error {
osSmtpPort := os.Getenv(constants.EnvKeySmtpPort)
osSmtpUsername := os.Getenv(constants.EnvKeySmtpUsername)
osSmtpPassword := os.Getenv(constants.EnvKeySmtpPassword)
osSmtpLocalName := os.Getenv(constants.EnvKeySmtpLocalName)
osSenderEmail := os.Getenv(constants.EnvKeySenderEmail)
osJwtType := os.Getenv(constants.EnvKeyJwtType)
osJwtSecret := os.Getenv(constants.EnvKeyJwtSecret)
@@ -205,6 +206,13 @@ func InitAllEnv() error {
envData[constants.EnvKeySmtpUsername] = osSmtpUsername
}
if val, ok := envData[constants.EnvKeySmtpLocalName]; !ok || val == "" {
envData[constants.EnvKeySmtpLocalName] = osSmtpLocalName
}
if osSmtpLocalName != "" && envData[constants.EnvKeySmtpLocalName] != osSmtpLocalName {
envData[constants.EnvKeySmtpLocalName] = osSmtpLocalName
}
if val, ok := envData[constants.EnvKeySmtpPassword]; !ok || val == "" {
envData[constants.EnvKeySmtpPassword] = osSmtpPassword
}

View File

@@ -17,6 +17,7 @@ require (
github.com/google/uuid v1.3.0
github.com/guregu/dynamo v1.16.0
github.com/joho/godotenv v1.3.0
github.com/mitchellh/gox v1.0.1 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/pelletier/go-toml/v2 v2.0.5 // indirect
github.com/robertkrimen/otto v0.0.0-20211024170158-b87d35c0b86f

View File

@@ -123,7 +123,6 @@ github.com/goccy/go-json v0.9.11 h1:/pAaQDLHEoCq/5FFmSKBswWmK6H0e8g4159Kc/X/nqk=
github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/gocql/gocql v1.2.0 h1:TZhsCd7fRuye4VyHr3WCvWwIQaZUmjsqnSIXK9FcVCE=
github.com/gocql/gocql v1.2.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/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gofrs/uuid v4.2.0+incompatible h1:yyYWMnhkhrKwwr8gAOcOCYxOOscHgDS9yZgBrnJfGa0=
github.com/gofrs/uuid v4.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
@@ -196,6 +195,8 @@ github.com/guregu/dynamo v1.16.0 h1:gmI8oi1VHwYQtq7+RPBeOiSssVLgxH/Az2t+NtDtL2c=
github.com/guregu/dynamo v1.16.0/go.mod h1:W2Gqcf3MtkrS+Q6fHPGAmRtT0Dyq+TGrqfqrUC9+R/c=
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/go-version v1.0.0 h1:21MVWPKDphxa7ineQQTrCU5brh7OuVVAzGOCnnCPtE8=
github.com/hashicorp/go-version v1.0.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
@@ -258,6 +259,7 @@ github.com/jinzhu/now v1.1.3 h1:PlHq1bSCSZL9K0wUhbm2pGLoTWs2GwVhsP6emvGV/ZI=
github.com/jinzhu/now v1.1.3/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
@@ -300,6 +302,10 @@ github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peK
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-sqlite3 v1.14.9 h1:10HX2Td0ocZpYEjhilsuo6WWtUqttj2Kb0KtD86/KYA=
github.com/mattn/go-sqlite3 v1.14.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mitchellh/gox v1.0.1 h1:x0jD3dcHk9a9xPSDN6YEL4xL6Qz0dvNYm8yZqui5chI=
github.com/mitchellh/gox v1.0.1/go.mod h1:ED6BioOGXMswlXa2zxfh/xdd5QhwYliBFn9V18Ap4z4=
github.com/mitchellh/iochan v1.0.0 h1:C+X3KsSTLFVBr/tK1eYN/vs4rJcvsiLU338UhYPJWeY=
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
github.com/mitchellh/mapstructure v1.3.1 h1:cCBH2gTD2K0OtLlv/Y5H01VQCqmlDxz30kS5Y5bqfLA=
github.com/mitchellh/mapstructure v1.3.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -492,12 +498,11 @@ golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwY
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20220930213112-107f3e3c3b0b h1:uKO3Js8lXGjpjdc4J3rqs0/Ex5yDKUGfk43tTYWVLas=
golang.org/x/net v0.0.0-20220930213112-107f3e3c3b0b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -561,14 +566,13 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec h1:BkDtF2Ih9xZ7le9ndzTA7KJow28VbQW3odyk/8drmuI=
golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=

View File

@@ -118,6 +118,7 @@ type ComplexityRoot struct {
ResetPasswordURL func(childComplexity int) int
Roles func(childComplexity int) int
SMTPHost func(childComplexity int) int
SMTPLocalName func(childComplexity int) int
SMTPPassword func(childComplexity int) int
SMTPPort func(childComplexity int) int
SMTPUsername func(childComplexity int) int
@@ -245,6 +246,7 @@ type ComplexityRoot struct {
}
ValidateJWTTokenResponse struct {
Claims func(childComplexity int) int
IsValid func(childComplexity int) int
}
@@ -805,6 +807,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.Env.SMTPHost(childComplexity), true
case "Env.SMTP_LOCAL_NAME":
if e.complexity.Env.SMTPLocalName == nil {
break
}
return e.complexity.Env.SMTPLocalName(childComplexity), true
case "Env.SMTP_PASSWORD":
if e.complexity.Env.SMTPPassword == nil {
break
@@ -1638,6 +1647,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.Users.Users(childComplexity), true
case "ValidateJWTTokenResponse.claims":
if e.complexity.ValidateJWTTokenResponse.Claims == nil {
break
}
return e.complexity.ValidateJWTTokenResponse.Claims(childComplexity), true
case "ValidateJWTTokenResponse.is_valid":
if e.complexity.ValidateJWTTokenResponse.IsValid == nil {
break
@@ -2059,6 +2075,7 @@ type Env {
SMTP_PORT: String
SMTP_USERNAME: String
SMTP_PASSWORD: String
SMTP_LOCAL_NAME: String
SENDER_EMAIL: String
JWT_TYPE: String
JWT_SECRET: String
@@ -2101,6 +2118,7 @@ type Env {
type ValidateJWTTokenResponse {
is_valid: Boolean!
claims: Map
}
type GenerateJWTKeysResponse {
@@ -2168,6 +2186,7 @@ input UpdateEnvInput {
SMTP_PORT: String
SMTP_USERNAME: String
SMTP_PASSWORD: String
SMTP_LOCAL_NAME: String
SENDER_EMAIL: String
JWT_TYPE: String
JWT_SECRET: String
@@ -4442,6 +4461,47 @@ func (ec *executionContext) fieldContext_Env_SMTP_PASSWORD(ctx context.Context,
return fc, nil
}
func (ec *executionContext) _Env_SMTP_LOCAL_NAME(ctx context.Context, field graphql.CollectedField, obj *model.Env) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_Env_SMTP_LOCAL_NAME(ctx, field)
if err != nil {
return graphql.Null
}
ctx = graphql.WithFieldContext(ctx, fc)
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
ret = graphql.Null
}
}()
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
return obj.SMTPLocalName, nil
})
if err != nil {
ec.Error(ctx, err)
return graphql.Null
}
if resTmp == nil {
return graphql.Null
}
res := resTmp.(*string)
fc.Result = res
return ec.marshalOString2ᚖstring(ctx, field.Selections, res)
}
func (ec *executionContext) fieldContext_Env_SMTP_LOCAL_NAME(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
fc = &graphql.FieldContext{
Object: "Env",
Field: field,
IsMethod: false,
IsResolver: false,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
return nil, errors.New("field of type String does not have child fields")
},
}
return fc, nil
}
func (ec *executionContext) _Env_SENDER_EMAIL(ctx context.Context, field graphql.CollectedField, obj *model.Env) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_Env_SENDER_EMAIL(ctx, field)
if err != nil {
@@ -9085,6 +9145,8 @@ func (ec *executionContext) fieldContext_Query_validate_jwt_token(ctx context.Co
switch field.Name {
case "is_valid":
return ec.fieldContext_ValidateJWTTokenResponse_is_valid(ctx, field)
case "claims":
return ec.fieldContext_ValidateJWTTokenResponse_claims(ctx, field)
}
return nil, fmt.Errorf("no field named %q was found under type ValidateJWTTokenResponse", field.Name)
},
@@ -9344,6 +9406,8 @@ func (ec *executionContext) fieldContext_Query__env(ctx context.Context, field g
return ec.fieldContext_Env_SMTP_USERNAME(ctx, field)
case "SMTP_PASSWORD":
return ec.fieldContext_Env_SMTP_PASSWORD(ctx, field)
case "SMTP_LOCAL_NAME":
return ec.fieldContext_Env_SMTP_LOCAL_NAME(ctx, field)
case "SENDER_EMAIL":
return ec.fieldContext_Env_SENDER_EMAIL(ctx, field)
case "JWT_TYPE":
@@ -10912,6 +10976,47 @@ func (ec *executionContext) fieldContext_ValidateJWTTokenResponse_is_valid(ctx c
return fc, nil
}
func (ec *executionContext) _ValidateJWTTokenResponse_claims(ctx context.Context, field graphql.CollectedField, obj *model.ValidateJWTTokenResponse) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_ValidateJWTTokenResponse_claims(ctx, field)
if err != nil {
return graphql.Null
}
ctx = graphql.WithFieldContext(ctx, fc)
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
ret = graphql.Null
}
}()
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
return obj.Claims, nil
})
if err != nil {
ec.Error(ctx, err)
return graphql.Null
}
if resTmp == nil {
return graphql.Null
}
res := resTmp.(map[string]interface{})
fc.Result = res
return ec.marshalOMap2map(ctx, field.Selections, res)
}
func (ec *executionContext) fieldContext_ValidateJWTTokenResponse_claims(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
fc = &graphql.FieldContext{
Object: "ValidateJWTTokenResponse",
Field: field,
IsMethod: false,
IsResolver: false,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
return nil, errors.New("field of type Map does not have child fields")
},
}
return fc, nil
}
func (ec *executionContext) _VerificationRequest_id(ctx context.Context, field graphql.CollectedField, obj *model.VerificationRequest) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_VerificationRequest_id(ctx, field)
if err != nil {
@@ -14970,7 +15075,7 @@ func (ec *executionContext) unmarshalInputUpdateEnvInput(ctx context.Context, ob
asMap[k] = v
}
fieldsInOrder := [...]string{"ACCESS_TOKEN_EXPIRY_TIME", "ADMIN_SECRET", "CUSTOM_ACCESS_TOKEN_SCRIPT", "OLD_ADMIN_SECRET", "SMTP_HOST", "SMTP_PORT", "SMTP_USERNAME", "SMTP_PASSWORD", "SENDER_EMAIL", "JWT_TYPE", "JWT_SECRET", "JWT_PRIVATE_KEY", "JWT_PUBLIC_KEY", "ALLOWED_ORIGINS", "APP_URL", "RESET_PASSWORD_URL", "APP_COOKIE_SECURE", "ADMIN_COOKIE_SECURE", "DISABLE_EMAIL_VERIFICATION", "DISABLE_BASIC_AUTHENTICATION", "DISABLE_MAGIC_LINK_LOGIN", "DISABLE_LOGIN_PAGE", "DISABLE_SIGN_UP", "DISABLE_REDIS_FOR_ENV", "DISABLE_STRONG_PASSWORD", "DISABLE_MULTI_FACTOR_AUTHENTICATION", "ENFORCE_MULTI_FACTOR_AUTHENTICATION", "ROLES", "PROTECTED_ROLES", "DEFAULT_ROLES", "JWT_ROLE_CLAIM", "GOOGLE_CLIENT_ID", "GOOGLE_CLIENT_SECRET", "GITHUB_CLIENT_ID", "GITHUB_CLIENT_SECRET", "FACEBOOK_CLIENT_ID", "FACEBOOK_CLIENT_SECRET", "LINKEDIN_CLIENT_ID", "LINKEDIN_CLIENT_SECRET", "APPLE_CLIENT_ID", "APPLE_CLIENT_SECRET", "TWITTER_CLIENT_ID", "TWITTER_CLIENT_SECRET", "ORGANIZATION_NAME", "ORGANIZATION_LOGO"}
fieldsInOrder := [...]string{"ACCESS_TOKEN_EXPIRY_TIME", "ADMIN_SECRET", "CUSTOM_ACCESS_TOKEN_SCRIPT", "OLD_ADMIN_SECRET", "SMTP_HOST", "SMTP_PORT", "SMTP_USERNAME", "SMTP_PASSWORD", "SMTP_LOCAL_NAME", "SENDER_EMAIL", "JWT_TYPE", "JWT_SECRET", "JWT_PRIVATE_KEY", "JWT_PUBLIC_KEY", "ALLOWED_ORIGINS", "APP_URL", "RESET_PASSWORD_URL", "APP_COOKIE_SECURE", "ADMIN_COOKIE_SECURE", "DISABLE_EMAIL_VERIFICATION", "DISABLE_BASIC_AUTHENTICATION", "DISABLE_MAGIC_LINK_LOGIN", "DISABLE_LOGIN_PAGE", "DISABLE_SIGN_UP", "DISABLE_REDIS_FOR_ENV", "DISABLE_STRONG_PASSWORD", "DISABLE_MULTI_FACTOR_AUTHENTICATION", "ENFORCE_MULTI_FACTOR_AUTHENTICATION", "ROLES", "PROTECTED_ROLES", "DEFAULT_ROLES", "JWT_ROLE_CLAIM", "GOOGLE_CLIENT_ID", "GOOGLE_CLIENT_SECRET", "GITHUB_CLIENT_ID", "GITHUB_CLIENT_SECRET", "FACEBOOK_CLIENT_ID", "FACEBOOK_CLIENT_SECRET", "LINKEDIN_CLIENT_ID", "LINKEDIN_CLIENT_SECRET", "APPLE_CLIENT_ID", "APPLE_CLIENT_SECRET", "TWITTER_CLIENT_ID", "TWITTER_CLIENT_SECRET", "ORGANIZATION_NAME", "ORGANIZATION_LOGO"}
for _, k := range fieldsInOrder {
v, ok := asMap[k]
if !ok {
@@ -15041,6 +15146,14 @@ func (ec *executionContext) unmarshalInputUpdateEnvInput(ctx context.Context, ob
if err != nil {
return it, err
}
case "SMTP_LOCAL_NAME":
var err error
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("SMTP_LOCAL_NAME"))
it.SMTPLocalName, err = ec.unmarshalOString2ᚖstring(ctx, v)
if err != nil {
return it, err
}
case "SENDER_EMAIL":
var err error
@@ -16026,6 +16139,10 @@ func (ec *executionContext) _Env(ctx context.Context, sel ast.SelectionSet, obj
out.Values[i] = ec._Env_SMTP_PASSWORD(ctx, field, obj)
case "SMTP_LOCAL_NAME":
out.Values[i] = ec._Env_SMTP_LOCAL_NAME(ctx, field, obj)
case "SENDER_EMAIL":
out.Values[i] = ec._Env_SENDER_EMAIL(ctx, field, obj)
@@ -17288,6 +17405,10 @@ func (ec *executionContext) _ValidateJWTTokenResponse(ctx context.Context, sel a
if out.Values[i] == graphql.Null {
invalids++
}
case "claims":
out.Values[i] = ec._ValidateJWTTokenResponse_claims(ctx, field, obj)
default:
panic("unknown field " + strconv.Quote(field.Name))
}

View File

@@ -74,6 +74,7 @@ type Env struct {
SMTPPort *string `json:"SMTP_PORT"`
SMTPUsername *string `json:"SMTP_USERNAME"`
SMTPPassword *string `json:"SMTP_PASSWORD"`
SMTPLocalName *string `json:"SMTP_LOCAL_NAME"`
SenderEmail *string `json:"SENDER_EMAIL"`
JwtType *string `json:"JWT_TYPE"`
JwtSecret *string `json:"JWT_SECRET"`
@@ -271,6 +272,7 @@ type UpdateEnvInput struct {
SMTPPort *string `json:"SMTP_PORT"`
SMTPUsername *string `json:"SMTP_USERNAME"`
SMTPPassword *string `json:"SMTP_PASSWORD"`
SMTPLocalName *string `json:"SMTP_LOCAL_NAME"`
SenderEmail *string `json:"SENDER_EMAIL"`
JwtType *string `json:"JWT_TYPE"`
JwtSecret *string `json:"JWT_SECRET"`
@@ -384,7 +386,8 @@ type ValidateJWTTokenInput struct {
}
type ValidateJWTTokenResponse struct {
IsValid bool `json:"is_valid"`
IsValid bool `json:"is_valid"`
Claims map[string]interface{} `json:"claims"`
}
type VerificationRequest struct {

View File

@@ -110,6 +110,7 @@ type Env {
SMTP_PORT: String
SMTP_USERNAME: String
SMTP_PASSWORD: String
SMTP_LOCAL_NAME: String
SENDER_EMAIL: String
JWT_TYPE: String
JWT_SECRET: String
@@ -152,6 +153,7 @@ type Env {
type ValidateJWTTokenResponse {
is_valid: Boolean!
claims: Map
}
type GenerateJWTKeysResponse {
@@ -219,6 +221,7 @@ input UpdateEnvInput {
SMTP_PORT: String
SMTP_USERNAME: String
SMTP_PASSWORD: String
SMTP_LOCAL_NAME: String
SENDER_EMAIL: String
JWT_TYPE: String
JWT_SECRET: String

View File

@@ -154,6 +154,7 @@ func TokenHandler() gin.HandlerFunc {
"error": "invalid_refresh_token",
"error_description": "The refresh token is invalid",
})
return
}
claims, err := token.ValidateRefreshToken(gc, refreshToken)
@@ -163,9 +164,10 @@ func TokenHandler() gin.HandlerFunc {
"error": "unauthorized",
"error_description": err.Error(),
})
return
}
userID = claims["sub"].(string)
loginMethod := claims["login_method"]
claimLoginMethod := claims["login_method"]
rolesInterface := claims["roles"].([]interface{})
scopeInterface := claims["scope"].([]interface{})
for _, v := range rolesInterface {
@@ -176,9 +178,11 @@ func TokenHandler() gin.HandlerFunc {
}
sessionKey = userID
if loginMethod != nil && loginMethod != "" {
sessionKey = loginMethod.(string) + ":" + sessionKey
if claimLoginMethod != nil && claimLoginMethod != "" {
sessionKey = claimLoginMethod.(string) + ":" + sessionKey
loginMethod = claimLoginMethod.(string)
}
// remove older refresh token and rotate it for security
go memorystore.Provider.DeleteUserSession(sessionKey, claims["nonce"].(string))
}
@@ -211,6 +215,7 @@ func TokenHandler() gin.HandlerFunc {
})
return
}
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeSessionToken+"_"+authToken.FingerPrint, authToken.FingerPrintHash)
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeAccessToken+"_"+authToken.FingerPrint, authToken.AccessToken.Token)
cookie.SetSession(gc, authToken.FingerPrintHash)

View File

@@ -89,6 +89,9 @@ func EnvResolver(ctx context.Context) (*model.Env, error) {
if val, ok := store[constants.EnvKeySenderEmail]; ok {
res.SenderEmail = refs.NewStringRef(val.(string))
}
if val, ok := store[constants.EnvKeySmtpLocalName]; ok {
res.SMTPLocalName = refs.NewStringRef(val.(string))
}
if val, ok := store[constants.EnvKeyJwtType]; ok {
res.JwtType = refs.NewStringRef(val.(string))
}

View File

@@ -62,12 +62,21 @@ func ForgotPasswordResolver(ctx context.Context, params model.ForgotPasswordInpu
log.Debug("Failed to generate nonce: ", err)
return res, err
}
redirectURL := parsers.GetAppURL(gc)
redirectURI := ""
// give higher preference to params redirect uri
if strings.TrimSpace(refs.StringValue(params.RedirectURI)) != "" {
redirectURL = refs.StringValue(params.RedirectURI)
redirectURI = refs.StringValue(params.RedirectURI)
} else {
redirectURI, err = memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyResetPasswordURL)
if err != nil {
log.Debug("ResetPasswordURL not found using default app url: ", err)
redirectURI = hostname + "/app/reset-password"
memorystore.Provider.UpdateEnvVariable(constants.EnvKeyResetPasswordURL, redirectURI)
}
}
verificationToken, err := token.CreateVerificationToken(params.Email, constants.VerificationTypeForgotPassword, hostname, nonceHash, redirectURL)
verificationToken, err := token.CreateVerificationToken(params.Email, constants.VerificationTypeForgotPassword, hostname, nonceHash, redirectURI)
if err != nil {
log.Debug("Failed to create verification token", err)
return res, err
@@ -78,7 +87,7 @@ func ForgotPasswordResolver(ctx context.Context, params model.ForgotPasswordInpu
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
Email: params.Email,
Nonce: nonceHash,
RedirectURI: redirectURL,
RedirectURI: redirectURI,
})
if err != nil {
log.Debug("Failed to add verification request", err)
@@ -89,7 +98,7 @@ func ForgotPasswordResolver(ctx context.Context, params model.ForgotPasswordInpu
go email.SendEmail([]string{params.Email}, constants.VerificationTypeForgotPassword, map[string]interface{}{
"user": user.ToMap(),
"organization": utils.GetOrganization(),
"verification_url": utils.GetForgotPasswordURL(verificationToken, hostname),
"verification_url": utils.GetForgotPasswordURL(verificationToken, redirectURI),
})
res = &model.Response{

View File

@@ -93,5 +93,6 @@ func ValidateJwtTokenResolver(ctx context.Context, params model.ValidateJWTToken
}
return &model.ValidateJWTTokenResponse{
IsValid: true,
Claims: claims,
}, nil
}

View File

@@ -2,7 +2,6 @@ package test
import (
"context"
"fmt"
"os"
"strings"
"testing"
@@ -63,24 +62,23 @@ func TestResolvers(t *testing.T) {
err := db.InitDB()
if err != nil {
t.Errorf("Error initializing database: %s", err.Error())
t.Logf("Error initializing database: %s", err.Error())
}
// clean the persisted config for test to use fresh config
envData, err := db.Provider.GetEnv(ctx)
fmt.Println("envData", envData.ID, envData.EnvData)
if err == nil && envData.ID != "" {
envData.EnvData = ""
_, err = db.Provider.UpdateEnv(ctx, envData)
if err != nil {
t.Errorf("Error updating env: %s", err.Error())
t.Logf("Error updating env: %s", err.Error())
}
} else if err != nil {
t.Errorf("Error getting env: %s", err.Error())
t.Logf("Error getting env: %s", err.Error())
}
err = env.PersistEnv()
if err != nil {
t.Errorf("Error persisting env: %s", err.Error())
t.Logf("Error persisting env: %s", err.Error())
}
memorystore.Provider.UpdateEnvVariable(constants.EnvKeyEnv, "test")

View File

@@ -93,5 +93,6 @@ func validateJwtTokenTest(t *testing.T, s TestSetup) {
})
assert.NoError(t, err)
assert.True(t, res.IsValid)
assert.Equal(t, user.Email, res.Claims["email"])
})
}

View File

@@ -114,16 +114,17 @@ func CreateRefreshToken(user models.User, roles, scopes []string, hostname, nonc
return "", 0, err
}
customClaims := jwt.MapClaims{
"iss": hostname,
"aud": clientID,
"sub": user.ID,
"exp": expiresAt,
"iat": time.Now().Unix(),
"token_type": constants.TokenTypeRefreshToken,
"roles": roles,
"scope": scopes,
"nonce": nonce,
"login_method": loginMethod,
"iss": hostname,
"aud": clientID,
"sub": user.ID,
"exp": expiresAt,
"iat": time.Now().Unix(),
"token_type": constants.TokenTypeRefreshToken,
"roles": roles,
"scope": scopes,
"nonce": nonce,
"login_method": loginMethod,
"allowed_roles": strings.Split(user.Roles, ","),
}
token, err := SignJWTToken(customClaims)
@@ -153,16 +154,17 @@ func CreateAccessToken(user models.User, roles, scopes []string, hostName, nonce
return "", 0, err
}
customClaims := jwt.MapClaims{
"iss": hostName,
"aud": clientID,
"nonce": nonce,
"sub": user.ID,
"exp": expiresAt,
"iat": time.Now().Unix(),
"token_type": constants.TokenTypeAccessToken,
"scope": scopes,
"roles": roles,
"login_method": loginMethod,
"iss": hostName,
"aud": clientID,
"nonce": nonce,
"sub": user.ID,
"exp": expiresAt,
"iat": time.Now().Unix(),
"token_type": constants.TokenTypeAccessToken,
"scope": scopes,
"roles": roles,
"login_method": loginMethod,
"allowed_roles": strings.Split(user.Roles, ","),
}
token, err := SignJWTToken(customClaims)
@@ -256,7 +258,6 @@ func ValidateRefreshToken(gc *gin.Context, refreshToken string) (map[string]inte
if loginMethod != nil && loginMethod != "" {
sessionKey = loginMethod.(string) + ":" + userID
}
token, err := memorystore.Provider.GetUserSession(sessionKey, constants.TokenTypeRefreshToken+"_"+nonce)
if nonce == "" || err != nil {
return res, fmt.Errorf(`unauthorized`)

View File

@@ -81,17 +81,8 @@ func GetOrganization() map[string]interface{} {
}
// GetForgotPasswordURL to get url for given token and hostname
func GetForgotPasswordURL(token, hostname string) string {
resetPasswordUrl, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyResetPasswordURL)
if err != nil {
return ""
}
if resetPasswordUrl == "" {
if err := memorystore.Provider.UpdateEnvVariable(constants.EnvKeyResetPasswordURL, hostname+"/app/reset-password"); err != nil {
return ""
}
}
verificationURL := resetPasswordUrl + "?token=" + token
func GetForgotPasswordURL(token, redirectURI string) string {
verificationURL := redirectURI + "?token=" + token
return verificationURL
}