Merge remote-tracking branch 'hub/main' into discours

This commit is contained in:
Untone 2024-04-15 09:31:44 +03:00
commit 5c33b159dc
60 changed files with 2099 additions and 1733 deletions

16
app/package-lock.json generated
View File

@ -9,7 +9,7 @@
"version": "1.0.0", "version": "1.0.0",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@authorizerdev/authorizer-react": "^1.2.0", "@authorizerdev/authorizer-react": "^1.3.1",
"@types/react": "^17.0.15", "@types/react": "^17.0.15",
"@types/react-dom": "^17.0.9", "@types/react-dom": "^17.0.9",
"esbuild": "^0.12.17", "esbuild": "^0.12.17",
@ -27,9 +27,9 @@
} }
}, },
"node_modules/@authorizerdev/authorizer-js": { "node_modules/@authorizerdev/authorizer-js": {
"version": "2.0.0-beta.3", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/@authorizerdev/authorizer-js/-/authorizer-js-2.0.0-beta.3.tgz", "resolved": "https://registry.npmjs.org/@authorizerdev/authorizer-js/-/authorizer-js-2.0.2.tgz",
"integrity": "sha512-cEzEVe7AewvOwOwoettiKRCq1e5Y33k9g8fJjqAoe3B/36iNN8wnZ5qgsPPZkqhv+Cvn6huj+YWtRimfVJ6d0w==", "integrity": "sha512-YgCtpaBDGYGMUlINFsvGNJnBtbnFG2wo66xX2i6auop52oVmKimvLpzOx8306/YddCxWhg9FljyVMp88Mbnxyw==",
"dependencies": { "dependencies": {
"cross-fetch": "^3.1.5" "cross-fetch": "^3.1.5"
}, },
@ -41,11 +41,11 @@
} }
}, },
"node_modules/@authorizerdev/authorizer-react": { "node_modules/@authorizerdev/authorizer-react": {
"version": "1.2.0", "version": "1.3.1",
"resolved": "https://registry.npmjs.org/@authorizerdev/authorizer-react/-/authorizer-react-1.2.0.tgz", "resolved": "https://registry.npmjs.org/@authorizerdev/authorizer-react/-/authorizer-react-1.3.1.tgz",
"integrity": "sha512-MtunZgh30rzY9jSADVP1DRC4sOBC82zx/yhK8O/1ufOAi7vTDZwPjDHIMrG/xWPNUYTCeFPEKpZlKyB+TH/M1w==", "integrity": "sha512-X7vQMr5jtZ28z+YZOt5ISB3lOYXNszpLpWw4S6VNs7TLAd5/ZP2kPaSdDbUgIvQFyYy51DHQeGygOu3G1n0Mdw==",
"dependencies": { "dependencies": {
"@authorizerdev/authorizer-js": "^2.0.0-beta.3", "@authorizerdev/authorizer-js": "^2.0.2",
"validator": "^13.11.0" "validator": "^13.11.0"
}, },
"engines": { "engines": {

View File

@ -12,7 +12,7 @@
"author": "Lakhan Samani", "author": "Lakhan Samani",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@authorizerdev/authorizer-react": "^1.2.0", "@authorizerdev/authorizer-react": "^1.3.1",
"@types/react": "^17.0.15", "@types/react": "^17.0.15",
"@types/react-dom": "^17.0.9", "@types/react-dom": "^17.0.9",
"esbuild": "^0.12.17", "esbuild": "^0.12.17",

View File

@ -33,7 +33,6 @@ export default function App() {
...window['__authorizer__'], ...window['__authorizer__'],
...urlProps, ...urlProps,
}; };
console.log({ globalState });
return ( return (
<div <div
style={{ style={{

File diff suppressed because it is too large Load Diff

View File

@ -53,7 +53,7 @@ const Features = ({ variables, setVariables }: any) => {
</Flex> </Flex>
<Flex> <Flex>
<Flex w="100%" justifyContent="start" alignItems="center"> <Flex w="100%" justifyContent="start" alignItems="center">
<Text fontSize="sm">Basic Authentication:</Text> <Text fontSize="sm">Email Basic Authentication:</Text>
</Flex> </Flex>
<Flex justifyContent="start"> <Flex justifyContent="start">
<InputField <InputField
@ -64,6 +64,19 @@ const Features = ({ variables, setVariables }: any) => {
/> />
</Flex> </Flex>
</Flex> </Flex>
<Flex>
<Flex w="100%" justifyContent="start" alignItems="center">
<Text fontSize="sm">Mobile Basic Authentication:</Text>
</Flex>
<Flex justifyContent="start">
<InputField
variables={variables}
setVariables={setVariables}
inputType={SwitchInputType.DISABLE_MOBILE_BASIC_AUTHENTICATION}
hasReversedValue
/>
</Flex>
</Flex>
<Flex> <Flex>
<Flex w="100%" justifyContent="start" alignItems="center"> <Flex w="100%" justifyContent="start" alignItems="center">
<Text fontSize="sm">Sign Up:</Text> <Text fontSize="sm">Sign Up:</Text>

View File

@ -83,6 +83,7 @@ export const SwitchInputType = {
DISABLE_MAGIC_LINK_LOGIN: 'DISABLE_MAGIC_LINK_LOGIN', DISABLE_MAGIC_LINK_LOGIN: 'DISABLE_MAGIC_LINK_LOGIN',
DISABLE_EMAIL_VERIFICATION: 'DISABLE_EMAIL_VERIFICATION', DISABLE_EMAIL_VERIFICATION: 'DISABLE_EMAIL_VERIFICATION',
DISABLE_BASIC_AUTHENTICATION: 'DISABLE_BASIC_AUTHENTICATION', DISABLE_BASIC_AUTHENTICATION: 'DISABLE_BASIC_AUTHENTICATION',
DISABLE_MOBILE_BASIC_AUTHENTICATION: 'DISABLE_MOBILE_BASIC_AUTHENTICATION',
DISABLE_SIGN_UP: 'DISABLE_SIGN_UP', DISABLE_SIGN_UP: 'DISABLE_SIGN_UP',
DISABLE_REDIS_FOR_ENV: 'DISABLE_REDIS_FOR_ENV', DISABLE_REDIS_FOR_ENV: 'DISABLE_REDIS_FOR_ENV',
DISABLE_STRONG_PASSWORD: 'DISABLE_STRONG_PASSWORD', DISABLE_STRONG_PASSWORD: 'DISABLE_STRONG_PASSWORD',
@ -167,6 +168,7 @@ export interface envVarTypes {
DISABLE_MAGIC_LINK_LOGIN: boolean; DISABLE_MAGIC_LINK_LOGIN: boolean;
DISABLE_EMAIL_VERIFICATION: boolean; DISABLE_EMAIL_VERIFICATION: boolean;
DISABLE_BASIC_AUTHENTICATION: boolean; DISABLE_BASIC_AUTHENTICATION: boolean;
DISABLE_MOBILE_BASIC_AUTHENTICATION: boolean;
DISABLE_SIGN_UP: boolean; DISABLE_SIGN_UP: boolean;
DISABLE_STRONG_PASSWORD: boolean; DISABLE_STRONG_PASSWORD: boolean;
OLD_ADMIN_SECRET: string; OLD_ADMIN_SECRET: string;

View File

@ -65,6 +65,7 @@ export const EnvVariablesQuery = `
DISABLE_MAGIC_LINK_LOGIN DISABLE_MAGIC_LINK_LOGIN
DISABLE_EMAIL_VERIFICATION DISABLE_EMAIL_VERIFICATION
DISABLE_BASIC_AUTHENTICATION DISABLE_BASIC_AUTHENTICATION
DISABLE_MOBILE_BASIC_AUTHENTICATION
DISABLE_SIGN_UP DISABLE_SIGN_UP
DISABLE_STRONG_PASSWORD DISABLE_STRONG_PASSWORD
DISABLE_REDIS_FOR_ENV DISABLE_REDIS_FOR_ENV
@ -97,6 +98,7 @@ export const UserDetailsQuery = `
id id
email email
email_verified email_verified
phone_number_verified
given_name given_name
family_name family_name
middle_name middle_name

View File

@ -86,6 +86,7 @@ const Environment = () => {
DISABLE_MAGIC_LINK_LOGIN: false, DISABLE_MAGIC_LINK_LOGIN: false,
DISABLE_EMAIL_VERIFICATION: false, DISABLE_EMAIL_VERIFICATION: false,
DISABLE_BASIC_AUTHENTICATION: false, DISABLE_BASIC_AUTHENTICATION: false,
DISABLE_MOBILE_BASIC_AUTHENTICATION: false,
DISABLE_SIGN_UP: false, DISABLE_SIGN_UP: false,
DISABLE_STRONG_PASSWORD: false, DISABLE_STRONG_PASSWORD: false,
OLD_ADMIN_SECRET: '', OLD_ADMIN_SECRET: '',

View File

@ -165,14 +165,25 @@ export default function Users() {
}; };
const userVerificationHandler = async (user: userDataTypes) => { const userVerificationHandler = async (user: userDataTypes) => {
const { id, email } = user; const { id, email, phone_number } = user;
const res = await client let params = {};
.mutation(UpdateUser, { if (email) {
params: { params = {
id, id,
email, email,
email_verified: true, email_verified: true,
}, };
}
if (phone_number) {
params = {
id,
phone_number,
phone_number_verified: true,
};
}
const res = await client
.mutation(UpdateUser, {
params,
}) })
.toPromise(); .toPromise();
if (res.error) { if (res.error) {
@ -298,7 +309,7 @@ export default function Users() {
<Table variant="simple"> <Table variant="simple">
<Thead> <Thead>
<Tr> <Tr>
<Th>Email</Th> <Th>Email / Phone</Th>
<Th>Created At</Th> <Th>Created At</Th>
<Th>Signup Methods</Th> <Th>Signup Methods</Th>
<Th>Roles</Th> <Th>Roles</Th>
@ -314,10 +325,15 @@ export default function Users() {
</Thead> </Thead>
<Tbody> <Tbody>
{userList.map((user: userDataTypes) => { {userList.map((user: userDataTypes) => {
const { email_verified, created_at, ...rest }: any = user; const {
email_verified,
phone_number_verified,
created_at,
...rest
}: any = user;
return ( return (
<Tr key={user.id} style={{ fontSize: 14 }}> <Tr key={user.id} style={{ fontSize: 14 }}>
<Td maxW="300">{user.email}</Td> <Td maxW="300">{user.email || user.phone_number}</Td>
<Td> <Td>
{dayjs(user.created_at * 1000).format('MMM DD, YYYY')} {dayjs(user.created_at * 1000).format('MMM DD, YYYY')}
</Td> </Td>
@ -327,9 +343,15 @@ export default function Users() {
<Tag <Tag
size="sm" size="sm"
variant="outline" variant="outline"
colorScheme={user.email_verified ? 'green' : 'yellow'} colorScheme={
user.email_verified || user.phone_number_verified
? 'green'
: 'yellow'
}
> >
{user.email_verified.toString()} {(
user.email_verified || user.phone_number_verified
).toString()}
</Tag> </Tag>
</Td> </Td>
<Td> <Td>
@ -368,7 +390,8 @@ export default function Users() {
</Flex> </Flex>
</MenuButton> </MenuButton>
<MenuList> <MenuList>
{!user.email_verified && ( {!user.email_verified &&
!user.phone_number_verified && (
<MenuItem <MenuItem
onClick={() => userVerificationHandler(user)} onClick={() => userVerificationHandler(user)}
> >

File diff suppressed because it is too large Load Diff

View File

@ -11,8 +11,8 @@ const (
type OTP struct { type OTP struct {
Key string `json:"_key,omitempty" bson:"_key,omitempty" cql:"_key,omitempty" dynamo:"key,omitempty"` // for arangodb Key string `json:"_key,omitempty" bson:"_key,omitempty" cql:"_key,omitempty" dynamo:"key,omitempty"` // for arangodb
ID string `gorm:"primaryKey;type:char(36)" json:"_id" bson:"_id" cql:"id" dynamo:"id,hash"` ID string `gorm:"primaryKey;type:char(36)" json:"_id" bson:"_id" cql:"id" dynamo:"id,hash"`
Email string `gorm:"unique" json:"email" bson:"email" cql:"email" dynamo:"email" index:"email,hash"` Email string `gorm:"index" json:"email" bson:"email" cql:"email" dynamo:"email" index:"email,hash"`
PhoneNumber string `gorm:"index:unique_index_phone_number,unique" json:"phone_number" bson:"phone_number" cql:"phone_number" dynamo:"phone_number"` PhoneNumber string `gorm:"index" json:"phone_number" bson:"phone_number" cql:"phone_number" dynamo:"phone_number"`
Otp string `json:"otp" bson:"otp" cql:"otp" dynamo:"otp"` Otp string `json:"otp" bson:"otp" cql:"otp" dynamo:"otp"`
ExpiresAt int64 `json:"expires_at" bson:"expires_at" cql:"expires_at" dynamo:"expires_at"` ExpiresAt int64 `json:"expires_at" bson:"expires_at" cql:"expires_at" dynamo:"expires_at"`
CreatedAt int64 `json:"created_at" bson:"created_at" cql:"created_at" dynamo:"created_at"` CreatedAt int64 `json:"created_at" bson:"created_at" cql:"created_at" dynamo:"created_at"`

View File

@ -15,7 +15,7 @@ type User struct {
Key string `json:"_key,omitempty" bson:"_key,omitempty" cql:"_key,omitempty" dynamo:"key,omitempty"` // for arangodb Key string `json:"_key,omitempty" bson:"_key,omitempty" cql:"_key,omitempty" dynamo:"key,omitempty"` // for arangodb
ID string `gorm:"primaryKey;type:char(36)" json:"_id" bson:"_id" cql:"id" dynamo:"id,hash"` ID string `gorm:"primaryKey;type:char(36)" json:"_id" bson:"_id" cql:"id" dynamo:"id,hash"`
Email *string `gorm:"unique" json:"email" bson:"email" cql:"email" dynamo:"email" index:"email,hash"` Email *string `gorm:"index" json:"email" bson:"email" cql:"email" dynamo:"email" index:"email,hash"`
EmailVerifiedAt *int64 `json:"email_verified_at" bson:"email_verified_at" cql:"email_verified_at" dynamo:"email_verified_at"` EmailVerifiedAt *int64 `json:"email_verified_at" bson:"email_verified_at" cql:"email_verified_at" dynamo:"email_verified_at"`
Password *string `json:"password" bson:"password" cql:"password" dynamo:"password"` Password *string `json:"password" bson:"password" cql:"password" dynamo:"password"`
SignupMethods string `json:"signup_methods" bson:"signup_methods" cql:"signup_methods" dynamo:"signup_methods"` SignupMethods string `json:"signup_methods" bson:"signup_methods" cql:"signup_methods" dynamo:"signup_methods"`

View File

@ -28,7 +28,7 @@ func (p *provider) AddAuthenticator(ctx context.Context, authenticators *models.
authenticatorsCollection, _ := p.db.Collection(ctx, models.Collections.Authenticators) authenticatorsCollection, _ := p.db.Collection(ctx, models.Collections.Authenticators)
meta, err := authenticatorsCollection.CreateDocument(arangoDriver.WithOverwrite(ctx), authenticators) meta, err := authenticatorsCollection.CreateDocument(arangoDriver.WithOverwrite(ctx), authenticators)
if err != nil { if err != nil {
return authenticators, err return nil, err
} }
authenticators.Key = meta.Key authenticators.Key = meta.Key
authenticators.ID = meta.ID.String() authenticators.ID = meta.ID.String()
@ -42,7 +42,7 @@ func (p *provider) UpdateAuthenticator(ctx context.Context, authenticators *mode
collection, _ := p.db.Collection(ctx, models.Collections.Authenticators) collection, _ := p.db.Collection(ctx, models.Collections.Authenticators)
meta, err := collection.UpdateDocument(ctx, authenticators.Key, authenticators) meta, err := collection.UpdateDocument(ctx, authenticators.Key, authenticators)
if err != nil { if err != nil {
return authenticators, err return nil, err
} }
authenticators.Key = meta.Key authenticators.Key = meta.Key
@ -59,7 +59,7 @@ func (p *provider) GetAuthenticatorDetailsByUserId(ctx context.Context, userId s
} }
cursor, err := p.db.Query(ctx, query, bindVars) cursor, err := p.db.Query(ctx, query, bindVars)
if err != nil { if err != nil {
return authenticators, err return nil, err
} }
defer cursor.Close() defer cursor.Close()
for { for {
@ -71,7 +71,7 @@ func (p *provider) GetAuthenticatorDetailsByUserId(ctx context.Context, userId s
} }
_, err := cursor.ReadDocument(ctx, &authenticators) _, err := cursor.ReadDocument(ctx, &authenticators)
if err != nil { if err != nil {
return authenticators, err return nil, err
} }
} }
return authenticators, nil return authenticators, nil

View File

@ -23,7 +23,7 @@ func (p *provider) AddEnv(ctx context.Context, env *models.Env) (*models.Env, er
configCollection, _ := p.db.Collection(ctx, models.Collections.Env) configCollection, _ := p.db.Collection(ctx, models.Collections.Env)
meta, err := configCollection.CreateDocument(arangoDriver.WithOverwrite(ctx), env) meta, err := configCollection.CreateDocument(arangoDriver.WithOverwrite(ctx), env)
if err != nil { if err != nil {
return env, err return nil, err
} }
env.Key = meta.Key env.Key = meta.Key
env.ID = meta.ID.String() env.ID = meta.ID.String()
@ -36,7 +36,7 @@ func (p *provider) UpdateEnv(ctx context.Context, env *models.Env) (*models.Env,
collection, _ := p.db.Collection(ctx, models.Collections.Env) collection, _ := p.db.Collection(ctx, models.Collections.Env)
meta, err := collection.UpdateDocument(ctx, env.Key, env) meta, err := collection.UpdateDocument(ctx, env.Key, env)
if err != nil { if err != nil {
return env, err return nil, err
} }
env.Key = meta.Key env.Key = meta.Key
@ -50,7 +50,7 @@ func (p *provider) GetEnv(ctx context.Context) (*models.Env, error) {
query := fmt.Sprintf("FOR d in %s RETURN d", models.Collections.Env) query := fmt.Sprintf("FOR d in %s RETURN d", models.Collections.Env)
cursor, err := p.db.Query(ctx, query, nil) cursor, err := p.db.Query(ctx, query, nil)
if err != nil { if err != nil {
return env, err return nil, err
} }
defer cursor.Close() defer cursor.Close()
for { for {
@ -62,7 +62,7 @@ func (p *provider) GetEnv(ctx context.Context) (*models.Env, error) {
} }
_, err := cursor.ReadDocument(ctx, &env) _, err := cursor.ReadDocument(ctx, &env)
if err != nil { if err != nil {
return env, err return nil, err
} }
} }

View File

@ -27,7 +27,7 @@ func (p *provider) AddUser(ctx context.Context, user *models.User) (*models.User
if user.Roles == "" { if user.Roles == "" {
defaultRoles, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyDefaultRoles) defaultRoles, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyDefaultRoles)
if err != nil { if err != nil {
return user, err return nil, err
} }
user.Roles = defaultRoles user.Roles = defaultRoles
} }
@ -36,6 +36,10 @@ func (p *provider) AddUser(ctx context.Context, user *models.User) (*models.User
if u, _ := p.GetUserByPhoneNumber(ctx, refs.StringValue(user.PhoneNumber)); u != nil && u.ID != user.ID { if u, _ := p.GetUserByPhoneNumber(ctx, refs.StringValue(user.PhoneNumber)); u != nil && u.ID != user.ID {
return user, fmt.Errorf("user with given phone number already exists") return user, fmt.Errorf("user with given phone number already exists")
} }
} else if user.Email != nil && strings.TrimSpace(refs.StringValue(user.Email)) != "" {
if u, _ := p.GetUserByEmail(ctx, refs.StringValue(user.Email)); u != nil && u.ID != user.ID {
return user, fmt.Errorf("user with given email already exists")
}
} }
user.CreatedAt = time.Now().Unix() user.CreatedAt = time.Now().Unix()
@ -43,7 +47,7 @@ func (p *provider) AddUser(ctx context.Context, user *models.User) (*models.User
userCollection, _ := p.db.Collection(ctx, models.Collections.User) userCollection, _ := p.db.Collection(ctx, models.Collections.User)
meta, err := userCollection.CreateDocument(arangoDriver.WithOverwrite(ctx), user) meta, err := userCollection.CreateDocument(arangoDriver.WithOverwrite(ctx), user)
if err != nil { if err != nil {
return user, err return nil, err
} }
user.Key = meta.Key user.Key = meta.Key
user.ID = meta.ID.String() user.ID = meta.ID.String()
@ -58,7 +62,7 @@ func (p *provider) UpdateUser(ctx context.Context, user *models.User) (*models.U
collection, _ := p.db.Collection(ctx, models.Collections.User) collection, _ := p.db.Collection(ctx, models.Collections.User)
meta, err := collection.UpdateDocument(ctx, user.Key, user) meta, err := collection.UpdateDocument(ctx, user.Key, user)
if err != nil { if err != nil {
return user, err return nil, err
} }
user.Key = meta.Key user.Key = meta.Key
@ -125,19 +129,19 @@ func (p *provider) GetUserByEmail(ctx context.Context, email string) (*models.Us
} }
cursor, err := p.db.Query(ctx, query, bindVars) cursor, err := p.db.Query(ctx, query, bindVars)
if err != nil { if err != nil {
return user, err return nil, err
} }
defer cursor.Close() defer cursor.Close()
for { for {
if !cursor.HasMore() { if !cursor.HasMore() {
if user == nil { if user == nil {
return user, fmt.Errorf("user not found") return nil, fmt.Errorf("user not found")
} }
break break
} }
_, err := cursor.ReadDocument(ctx, &user) _, err := cursor.ReadDocument(ctx, &user)
if err != nil { if err != nil {
return user, err return nil, err
} }
} }
return user, nil return user, nil
@ -152,19 +156,19 @@ func (p *provider) GetUserByID(ctx context.Context, id string) (*models.User, er
} }
cursor, err := p.db.Query(ctx, query, bindVars) cursor, err := p.db.Query(ctx, query, bindVars)
if err != nil { if err != nil {
return user, err return nil, err
} }
defer cursor.Close() defer cursor.Close()
for { for {
if !cursor.HasMore() { if !cursor.HasMore() {
if user == nil { if user == nil {
return user, fmt.Errorf("user not found") return nil, fmt.Errorf("user not found")
} }
break break
} }
_, err := cursor.ReadDocument(ctx, &user) _, err := cursor.ReadDocument(ctx, &user)
if err != nil { if err != nil {
return user, err return nil, err
} }
} }
return user, nil return user, nil

View File

@ -22,7 +22,7 @@ func (p *provider) AddVerificationRequest(ctx context.Context, verificationReque
verificationRequestRequestCollection, _ := p.db.Collection(ctx, models.Collections.VerificationRequest) verificationRequestRequestCollection, _ := p.db.Collection(ctx, models.Collections.VerificationRequest)
meta, err := verificationRequestRequestCollection.CreateDocument(ctx, verificationRequest) meta, err := verificationRequestRequestCollection.CreateDocument(ctx, verificationRequest)
if err != nil { if err != nil {
return verificationRequest, err return nil, err
} }
verificationRequest.Key = meta.Key verificationRequest.Key = meta.Key
verificationRequest.ID = meta.ID.String() verificationRequest.ID = meta.ID.String()
@ -38,7 +38,7 @@ func (p *provider) GetVerificationRequestByToken(ctx context.Context, token stri
} }
cursor, err := p.db.Query(ctx, query, bindVars) cursor, err := p.db.Query(ctx, query, bindVars)
if err != nil { if err != nil {
return verificationRequest, err return nil, err
} }
defer cursor.Close() defer cursor.Close()
for { for {
@ -50,7 +50,7 @@ func (p *provider) GetVerificationRequestByToken(ctx context.Context, token stri
} }
_, err := cursor.ReadDocument(ctx, &verificationRequest) _, err := cursor.ReadDocument(ctx, &verificationRequest)
if err != nil { if err != nil {
return verificationRequest, err return nil, err
} }
} }
return verificationRequest, nil return verificationRequest, nil
@ -66,7 +66,7 @@ func (p *provider) GetVerificationRequestByEmail(ctx context.Context, email stri
} }
cursor, err := p.db.Query(ctx, query, bindVars) cursor, err := p.db.Query(ctx, query, bindVars)
if err != nil { if err != nil {
return verificationRequest, err return nil, err
} }
defer cursor.Close() defer cursor.Close()
for { for {
@ -78,7 +78,7 @@ func (p *provider) GetVerificationRequestByEmail(ctx context.Context, email stri
} }
_, err := cursor.ReadDocument(ctx, &verificationRequest) _, err := cursor.ReadDocument(ctx, &verificationRequest)
if err != nil { if err != nil {
return verificationRequest, err return nil, err
} }
} }
return verificationRequest, nil return verificationRequest, nil

View File

@ -29,7 +29,7 @@ func (p *provider) AddAuthenticator(ctx context.Context, authenticators *models.
bytes, err := json.Marshal(authenticators) bytes, err := json.Marshal(authenticators)
if err != nil { if err != nil {
return authenticators, err return nil, err
} }
// use decoder instead of json.Unmarshall, because it converts int64 -> float64 after unmarshalling // use decoder instead of json.Unmarshall, because it converts int64 -> float64 after unmarshalling
@ -38,7 +38,7 @@ func (p *provider) AddAuthenticator(ctx context.Context, authenticators *models.
authenticatorsMap := map[string]interface{}{} authenticatorsMap := map[string]interface{}{}
err = decoder.Decode(&authenticatorsMap) err = decoder.Decode(&authenticatorsMap)
if err != nil { if err != nil {
return authenticators, err return nil, err
} }
fields := "(" fields := "("
@ -66,7 +66,7 @@ func (p *provider) AddAuthenticator(ctx context.Context, authenticators *models.
query := fmt.Sprintf("INSERT INTO %s %s VALUES %s IF NOT EXISTS", KeySpace+"."+models.Collections.Authenticators, fields, values) query := fmt.Sprintf("INSERT INTO %s %s VALUES %s IF NOT EXISTS", KeySpace+"."+models.Collections.Authenticators, fields, values)
err = p.db.Query(query).Exec() err = p.db.Query(query).Exec()
if err != nil { if err != nil {
return authenticators, err return nil, err
} }
return authenticators, nil return authenticators, nil
@ -77,7 +77,7 @@ func (p *provider) UpdateAuthenticator(ctx context.Context, authenticators *mode
bytes, err := json.Marshal(authenticators) bytes, err := json.Marshal(authenticators)
if err != nil { if err != nil {
return authenticators, err return nil, err
} }
// use decoder instead of json.Unmarshall, because it converts int64 -> float64 after unmarshalling // use decoder instead of json.Unmarshall, because it converts int64 -> float64 after unmarshalling
decoder := json.NewDecoder(strings.NewReader(string(bytes))) decoder := json.NewDecoder(strings.NewReader(string(bytes)))
@ -85,7 +85,7 @@ func (p *provider) UpdateAuthenticator(ctx context.Context, authenticators *mode
authenticatorsMap := map[string]interface{}{} authenticatorsMap := map[string]interface{}{}
err = decoder.Decode(&authenticatorsMap) err = decoder.Decode(&authenticatorsMap)
if err != nil { if err != nil {
return authenticators, err return nil, err
} }
updateFields := "" updateFields := ""
@ -116,7 +116,7 @@ func (p *provider) UpdateAuthenticator(ctx context.Context, authenticators *mode
query := fmt.Sprintf("UPDATE %s SET %s WHERE id = '%s'", KeySpace+"."+models.Collections.Authenticators, updateFields, authenticators.ID) query := fmt.Sprintf("UPDATE %s SET %s WHERE id = '%s'", KeySpace+"."+models.Collections.Authenticators, updateFields, authenticators.ID)
err = p.db.Query(query).Exec() err = p.db.Query(query).Exec()
if err != nil { if err != nil {
return authenticators, err return nil, err
} }
return authenticators, nil return authenticators, nil

View File

@ -20,7 +20,7 @@ func (p *provider) AddEnv(ctx context.Context, env *models.Env) (*models.Env, er
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) 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() err := p.db.Query(insertEnvQuery).Exec()
if err != nil { if err != nil {
return env, err return nil, err
} }
return env, nil return env, nil
@ -32,7 +32,7 @@ func (p *provider) UpdateEnv(ctx context.Context, env *models.Env) (*models.Env,
updateEnvQuery := fmt.Sprintf("UPDATE %s SET env = '%s', updated_at = %d WHERE id = '%s'", KeySpace+"."+models.Collections.Env, env.EnvData, env.UpdatedAt, env.ID) 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() err := p.db.Query(updateEnvQuery).Exec()
if err != nil { if err != nil {
return env, err return nil, err
} }
return env, nil return env, nil
} }

View File

@ -26,7 +26,7 @@ func (p *provider) AddUser(ctx context.Context, user *models.User) (*models.User
if user.Roles == "" { if user.Roles == "" {
defaultRoles, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyDefaultRoles) defaultRoles, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyDefaultRoles)
if err != nil { if err != nil {
return user, err return nil, err
} }
user.Roles = defaultRoles user.Roles = defaultRoles
} }
@ -35,6 +35,10 @@ func (p *provider) AddUser(ctx context.Context, user *models.User) (*models.User
if u, _ := p.GetUserByPhoneNumber(ctx, refs.StringValue(user.PhoneNumber)); u != nil && u.ID != user.ID { if u, _ := p.GetUserByPhoneNumber(ctx, refs.StringValue(user.PhoneNumber)); u != nil && u.ID != user.ID {
return user, fmt.Errorf("user with given phone number already exists") return user, fmt.Errorf("user with given phone number already exists")
} }
} else if user.Email != nil && strings.TrimSpace(refs.StringValue(user.Email)) != "" {
if u, _ := p.GetUserByEmail(ctx, refs.StringValue(user.Email)); u != nil && u.ID != user.ID {
return user, fmt.Errorf("user with given email already exists")
}
} }
user.CreatedAt = time.Now().Unix() user.CreatedAt = time.Now().Unix()
@ -42,7 +46,7 @@ func (p *provider) AddUser(ctx context.Context, user *models.User) (*models.User
bytes, err := json.Marshal(user) bytes, err := json.Marshal(user)
if err != nil { if err != nil {
return user, err return nil, err
} }
// use decoder instead of json.Unmarshall, because it converts int64 -> float64 after unmarshalling // use decoder instead of json.Unmarshall, because it converts int64 -> float64 after unmarshalling
@ -51,7 +55,7 @@ func (p *provider) AddUser(ctx context.Context, user *models.User) (*models.User
userMap := map[string]interface{}{} userMap := map[string]interface{}{}
err = decoder.Decode(&userMap) err = decoder.Decode(&userMap)
if err != nil { if err != nil {
return user, err return nil, err
} }
fields := "(" fields := "("
@ -80,7 +84,7 @@ func (p *provider) AddUser(ctx context.Context, user *models.User) (*models.User
err = p.db.Query(query).Exec() err = p.db.Query(query).Exec()
if err != nil { if err != nil {
return user, err return nil, err
} }
return user, nil return user, nil
@ -92,7 +96,7 @@ func (p *provider) UpdateUser(ctx context.Context, user *models.User) (*models.U
bytes, err := json.Marshal(user) bytes, err := json.Marshal(user)
if err != nil { if err != nil {
return user, err return nil, err
} }
// use decoder instead of json.Unmarshall, because it converts int64 -> float64 after unmarshalling // use decoder instead of json.Unmarshall, because it converts int64 -> float64 after unmarshalling
decoder := json.NewDecoder(strings.NewReader(string(bytes))) decoder := json.NewDecoder(strings.NewReader(string(bytes)))
@ -100,7 +104,7 @@ func (p *provider) UpdateUser(ctx context.Context, user *models.User) (*models.U
userMap := map[string]interface{}{} userMap := map[string]interface{}{}
err = decoder.Decode(&userMap) err = decoder.Decode(&userMap)
if err != nil { if err != nil {
return user, err return nil, err
} }
updateFields := "" updateFields := ""
@ -131,7 +135,7 @@ func (p *provider) UpdateUser(ctx context.Context, user *models.User) (*models.U
query := fmt.Sprintf("UPDATE %s SET %s WHERE id = '%s'", KeySpace+"."+models.Collections.User, updateFields, user.ID) query := fmt.Sprintf("UPDATE %s SET %s WHERE id = '%s'", KeySpace+"."+models.Collections.User, updateFields, user.ID)
err = p.db.Query(query).Exec() err = p.db.Query(query).Exec()
if err != nil { if err != nil {
return user, err return nil, err
} }
return user, nil return user, nil

View File

@ -23,7 +23,7 @@ func (p *provider) AddVerificationRequest(ctx context.Context, verificationReque
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) 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() err := p.db.Query(query).Exec()
if err != nil { if err != nil {
return verificationRequest, err return nil, err
} }
return verificationRequest, nil return verificationRequest, nil
} }

View File

@ -30,7 +30,7 @@ func (p *provider) AddAuthenticator(ctx context.Context, authenticators *models.
} }
_, err := p.db.Collection(models.Collections.Authenticators).Insert(authenticators.ID, authenticators, &insertOpt) _, err := p.db.Collection(models.Collections.Authenticators).Insert(authenticators.ID, authenticators, &insertOpt)
if err != nil { if err != nil {
return authenticators, err return nil, err
} }
return authenticators, nil return authenticators, nil
} }
@ -71,11 +71,11 @@ func (p *provider) GetAuthenticatorDetailsByUserId(ctx context.Context, userId s
PositionalParameters: []interface{}{userId, authenticatorType}, PositionalParameters: []interface{}{userId, authenticatorType},
}) })
if err != nil { if err != nil {
return authenticators, err return nil, err
} }
err = q.One(&authenticators) err = q.One(&authenticators)
if err != nil { if err != nil {
return authenticators, err return nil, err
} }
return authenticators, nil return authenticators, nil
} }

View File

@ -24,7 +24,7 @@ func (p *provider) AddEnv(ctx context.Context, env *models.Env) (*models.Env, er
} }
_, err := p.db.Collection(models.Collections.Env).Insert(env.ID, env, &insertOpt) _, err := p.db.Collection(models.Collections.Env).Insert(env.ID, env, &insertOpt)
if err != nil { if err != nil {
return env, err return nil, err
} }
return env, nil return env, nil
} }
@ -40,7 +40,7 @@ func (p *provider) UpdateEnv(ctx context.Context, env *models.Env) (*models.Env,
PositionalParameters: []interface{}{env.EnvData, env.UpdatedAt, env.UpdatedAt, env.ID}, PositionalParameters: []interface{}{env.EnvData, env.UpdatedAt, env.UpdatedAt, env.ID},
}) })
if err != nil { if err != nil {
return env, err return nil, err
} }
return env, nil return env, nil
} }
@ -55,11 +55,11 @@ func (p *provider) GetEnv(ctx context.Context) (*models.Env, error) {
ScanConsistency: gocb.QueryScanConsistencyRequestPlus, ScanConsistency: gocb.QueryScanConsistencyRequestPlus,
}) })
if err != nil { if err != nil {
return env, err return nil, err
} }
err = q.One(&env) err = q.One(&env)
if err != nil { if err != nil {
return env, err return nil, err
} }
env.Hash = env.EncryptionKey env.Hash = env.EncryptionKey
return env, nil return env, nil

View File

@ -50,7 +50,7 @@ func (p *provider) UpsertOTP(ctx context.Context, otpParam *models.OTP) (*models
} }
_, err := p.db.Collection(models.Collections.OTP).Insert(otp.ID, otp, &insertOpt) _, err := p.db.Collection(models.Collections.OTP).Insert(otp.ID, otp, &insertOpt)
if err != nil { if err != nil {
return otp, err return nil, err
} }
} else { } else {
query := fmt.Sprintf(`UPDATE %s.%s SET otp=$1, expires_at=$2, updated_at=$3 WHERE _id=$4`, p.scopeName, models.Collections.OTP) query := fmt.Sprintf(`UPDATE %s.%s SET otp=$1, expires_at=$2, updated_at=$3 WHERE _id=$4`, p.scopeName, models.Collections.OTP)
@ -58,7 +58,7 @@ func (p *provider) UpsertOTP(ctx context.Context, otpParam *models.OTP) (*models
PositionalParameters: []interface{}{otp.Otp, otp.ExpiresAt, otp.UpdatedAt, otp.ID}, PositionalParameters: []interface{}{otp.Otp, otp.ExpiresAt, otp.UpdatedAt, otp.ID},
}) })
if err != nil { if err != nil {
return otp, err return nil, err
} }
} }
return otp, nil return otp, nil

View File

@ -127,7 +127,7 @@ func CreateBucketAndScope(cluster *gocb.Cluster, bucketName string, scopeName st
if scopeName != defaultScope { if scopeName != defaultScope {
err = bucket.Collections().CreateScope(scopeName, nil) err = bucket.Collections().CreateScope(scopeName, nil)
if err != nil && !errors.Is(err, gocb.ErrScopeExists) { if err != nil && !errors.Is(err, gocb.ErrScopeExists) {
return bucket, err return nil, err
} }
} }
return bucket, nil return bucket, nil

View File

@ -47,7 +47,7 @@ func (p *provider) GetTotalDocs(ctx context.Context, collection string) (int64,
}) })
queryRes.One(&totalDocs) queryRes.One(&totalDocs)
if err != nil { if err != nil {
return totalDocs.Total, err return 0, err
} }
return totalDocs.Total, nil return totalDocs.Total, nil
} }

View File

@ -4,12 +4,14 @@ import (
"context" "context"
"fmt" "fmt"
"log" "log"
"strings"
"time" "time"
"github.com/authorizerdev/authorizer/server/constants" "github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/db/models" "github.com/authorizerdev/authorizer/server/db/models"
"github.com/authorizerdev/authorizer/server/graph/model" "github.com/authorizerdev/authorizer/server/graph/model"
"github.com/authorizerdev/authorizer/server/memorystore" "github.com/authorizerdev/authorizer/server/memorystore"
"github.com/authorizerdev/authorizer/server/refs"
"github.com/couchbase/gocb/v2" "github.com/couchbase/gocb/v2"
"github.com/google/uuid" "github.com/google/uuid"
) )
@ -23,11 +25,21 @@ func (p *provider) AddUser(ctx context.Context, user *models.User) (*models.User
if user.Roles == "" { if user.Roles == "" {
defaultRoles, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyDefaultRoles) defaultRoles, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyDefaultRoles)
if err != nil { if err != nil {
return user, err return nil, err
} }
user.Roles = defaultRoles user.Roles = defaultRoles
} }
if user.PhoneNumber != nil && strings.TrimSpace(refs.StringValue(user.PhoneNumber)) != "" {
if u, _ := p.GetUserByPhoneNumber(ctx, refs.StringValue(user.PhoneNumber)); u != nil && u.ID != user.ID {
return user, fmt.Errorf("user with given phone number already exists")
}
} else if user.Email != nil && strings.TrimSpace(refs.StringValue(user.Email)) != "" {
if u, _ := p.GetUserByEmail(ctx, refs.StringValue(user.Email)); u != nil && u.ID != user.ID {
return user, fmt.Errorf("user with given email already exists")
}
}
user.CreatedAt = time.Now().Unix() user.CreatedAt = time.Now().Unix()
user.UpdatedAt = time.Now().Unix() user.UpdatedAt = time.Now().Unix()
insertOpt := gocb.InsertOptions{ insertOpt := gocb.InsertOptions{
@ -35,7 +47,7 @@ func (p *provider) AddUser(ctx context.Context, user *models.User) (*models.User
} }
_, err := p.db.Collection(models.Collections.User).Insert(user.ID, user, &insertOpt) _, err := p.db.Collection(models.Collections.User).Insert(user.ID, user, &insertOpt)
if err != nil { if err != nil {
return user, err return nil, err
} }
return user, nil return user, nil
} }
@ -48,7 +60,7 @@ func (p *provider) UpdateUser(ctx context.Context, user *models.User) (*models.U
} }
_, err := p.db.Collection(models.Collections.User).Upsert(user.ID, user, &upsertOpt) _, err := p.db.Collection(models.Collections.User).Upsert(user.ID, user, &upsertOpt)
if err != nil { if err != nil {
return user, err return nil, err
} }
return user, nil return user, nil
} }
@ -110,11 +122,11 @@ func (p *provider) GetUserByEmail(ctx context.Context, email string) (*models.Us
PositionalParameters: []interface{}{email}, PositionalParameters: []interface{}{email},
}) })
if err != nil { if err != nil {
return user, err return nil, err
} }
err = q.One(&user) err = q.One(&user)
if err != nil { if err != nil {
return user, err return nil, err
} }
return user, nil return user, nil
} }
@ -129,11 +141,11 @@ func (p *provider) GetUserByID(ctx context.Context, id string) (*models.User, er
PositionalParameters: []interface{}{id}, PositionalParameters: []interface{}{id},
}) })
if err != nil { if err != nil {
return user, err return nil, err
} }
err = q.One(&user) err = q.One(&user)
if err != nil { if err != nil {
return user, err return nil, err
} }
return user, nil return user, nil
} }
@ -182,11 +194,11 @@ func (p *provider) GetUserByPhoneNumber(ctx context.Context, phoneNumber string)
PositionalParameters: []interface{}{phoneNumber}, PositionalParameters: []interface{}{phoneNumber},
}) })
if err != nil { if err != nil {
return user, err return nil, err
} }
err = q.One(&user) err = q.One(&user)
if err != nil { if err != nil {
return user, err return nil, err
} }
return user, nil return user, nil
} }

View File

@ -25,7 +25,7 @@ func (p *provider) AddVerificationRequest(ctx context.Context, verificationReque
} }
_, err := p.db.Collection(models.Collections.VerificationRequest).Insert(verificationRequest.ID, verificationRequest, &insertOpt) _, err := p.db.Collection(models.Collections.VerificationRequest).Insert(verificationRequest.ID, verificationRequest, &insertOpt)
if err != nil { if err != nil {
return verificationRequest, err return nil, err
} }
return verificationRequest, nil return verificationRequest, nil
} }
@ -44,12 +44,12 @@ func (p *provider) GetVerificationRequestByToken(ctx context.Context, token stri
}) })
if err != nil { if err != nil {
return verificationRequest, err return nil, err
} }
err = queryResult.One(&verificationRequest) err = queryResult.One(&verificationRequest)
if err != nil { if err != nil {
return verificationRequest, err return nil, err
} }
return verificationRequest, nil return verificationRequest, nil
} }
@ -69,7 +69,7 @@ func (p *provider) GetVerificationRequestByEmail(ctx context.Context, email stri
var verificationRequest *models.VerificationRequest var verificationRequest *models.VerificationRequest
err = queryResult.One(&verificationRequest) err = queryResult.One(&verificationRequest)
if err != nil { if err != nil {
return verificationRequest, err return nil, err
} }
return verificationRequest, nil return verificationRequest, nil
} }

View File

@ -29,7 +29,7 @@ func (p *provider) AddWebhook(ctx context.Context, webhook *models.Webhook) (*mo
} }
_, err := p.db.Collection(models.Collections.Webhook).Insert(webhook.ID, webhook, &insertOpt) _, err := p.db.Collection(models.Collections.Webhook).Insert(webhook.ID, webhook, &insertOpt)
if err != nil { if err != nil {
return webhook.AsAPIWebhook(), err return nil, err
} }
return webhook.AsAPIWebhook(), nil return webhook.AsAPIWebhook(), nil
} }

View File

@ -25,7 +25,7 @@ func (p *provider) AddWebhookLog(ctx context.Context, webhookLog *models.Webhook
} }
_, err := p.db.Collection(models.Collections.WebhookLog).Insert(webhookLog.ID, webhookLog, &insertOpt) _, err := p.db.Collection(models.Collections.WebhookLog).Insert(webhookLog.ID, webhookLog, &insertOpt)
if err != nil { if err != nil {
return webhookLog.AsAPIWebhookLog(), err return nil, err
} }
return webhookLog.AsAPIWebhookLog(), nil return webhookLog.AsAPIWebhookLog(), nil
} }

View File

@ -24,7 +24,7 @@ func (p *provider) AddAuthenticator(ctx context.Context, authenticators *models.
authenticators.UpdatedAt = time.Now().Unix() authenticators.UpdatedAt = time.Now().Unix()
err := collection.Put(authenticators).RunWithContext(ctx) err := collection.Put(authenticators).RunWithContext(ctx)
if err != nil { if err != nil {
return authenticators, err return nil, err
} }
return authenticators, nil return authenticators, nil
} }
@ -35,7 +35,7 @@ func (p *provider) UpdateAuthenticator(ctx context.Context, authenticators *mode
authenticators.UpdatedAt = time.Now().Unix() authenticators.UpdatedAt = time.Now().Unix()
err := UpdateByHashKey(collection, "id", authenticators.ID, authenticators) err := UpdateByHashKey(collection, "id", authenticators.ID, authenticators)
if err != nil { if err != nil {
return authenticators, err return nil, err
} }
} }
return authenticators, nil return authenticators, nil
@ -51,7 +51,7 @@ func (p *provider) GetAuthenticatorDetailsByUserId(ctx context.Context, userId s
} }
err := iter.Err() err := iter.Err()
if err != nil { if err != nil {
return authenticators, err return nil, err
} }
return authenticators, nil return authenticators, nil
} }

View File

@ -21,7 +21,7 @@ func (p *provider) AddEnv(ctx context.Context, env *models.Env) (*models.Env, er
env.UpdatedAt = time.Now().Unix() env.UpdatedAt = time.Now().Unix()
err := collection.Put(env).RunWithContext(ctx) err := collection.Put(env).RunWithContext(ctx)
if err != nil { if err != nil {
return env, err return nil, err
} }
return env, nil return env, nil
} }
@ -32,7 +32,7 @@ func (p *provider) UpdateEnv(ctx context.Context, env *models.Env) (*models.Env,
env.UpdatedAt = time.Now().Unix() env.UpdatedAt = time.Now().Unix()
err := UpdateByHashKey(collection, "id", env.ID, env) err := UpdateByHashKey(collection, "id", env.ID, env)
if err != nil { if err != nil {
return env, err return nil, err
} }
return env, nil return env, nil
} }
@ -45,7 +45,7 @@ func (p *provider) GetEnv(ctx context.Context) (*models.Env, error) {
iter := collection.Scan().Limit(1).Iter() iter := collection.Scan().Limit(1).Iter()
for iter.NextWithContext(ctx, &env) { for iter.NextWithContext(ctx, &env) {
if env == nil { if env == nil {
return env, errors.New("no documets found") return nil, errors.New("no documets found")
} else { } else {
return env, nil return env, nil
} }

View File

@ -26,20 +26,24 @@ func (p *provider) AddUser(ctx context.Context, user *models.User) (*models.User
if user.Roles == "" { if user.Roles == "" {
defaultRoles, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyDefaultRoles) defaultRoles, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyDefaultRoles)
if err != nil { if err != nil {
return user, err return nil, err
} }
user.Roles = defaultRoles user.Roles = defaultRoles
} }
if user.PhoneNumber != nil && strings.TrimSpace(refs.StringValue(user.PhoneNumber)) != "" { if user.PhoneNumber != nil && strings.TrimSpace(refs.StringValue(user.PhoneNumber)) != "" {
if u, _ := p.GetUserByPhoneNumber(ctx, refs.StringValue(user.PhoneNumber)); u != nil { if u, _ := p.GetUserByPhoneNumber(ctx, refs.StringValue(user.PhoneNumber)); u != nil && u.ID != user.ID {
return user, fmt.Errorf("user with given phone number already exists") return user, fmt.Errorf("user with given phone number already exists")
} }
} else if user.Email != nil && strings.TrimSpace(refs.StringValue(user.Email)) != "" {
if u, _ := p.GetUserByEmail(ctx, refs.StringValue(user.Email)); u != nil && u.ID != user.ID {
return user, fmt.Errorf("user with given email already exists")
}
} }
user.CreatedAt = time.Now().Unix() user.CreatedAt = time.Now().Unix()
user.UpdatedAt = time.Now().Unix() user.UpdatedAt = time.Now().Unix()
err := collection.Put(user).RunWithContext(ctx) err := collection.Put(user).RunWithContext(ctx)
if err != nil { if err != nil {
return user, err return nil, err
} }
return user, nil return user, nil
} }
@ -51,7 +55,7 @@ func (p *provider) UpdateUser(ctx context.Context, user *models.User) (*models.U
user.UpdatedAt = time.Now().Unix() user.UpdatedAt = time.Now().Unix()
err := UpdateByHashKey(collection, "id", user.ID, user) err := UpdateByHashKey(collection, "id", user.ID, user)
if err != nil { if err != nil {
return user, err return nil, err
} }
} }
return user, nil return user, nil
@ -122,7 +126,7 @@ func (p *provider) GetUserByEmail(ctx context.Context, email string) (*models.Us
user = users[0] user = users[0]
return user, nil return user, nil
} else { } else {
return user, errors.New("no record found") return nil, errors.New("no record found")
} }
} }
@ -133,7 +137,7 @@ func (p *provider) GetUserByID(ctx context.Context, id string) (*models.User, er
err := collection.Get("id", id).OneWithContext(ctx, &user) err := collection.Get("id", id).OneWithContext(ctx, &user)
if err != nil { if err != nil {
if refs.StringValue(user.Email) == "" { if refs.StringValue(user.Email) == "" {
return user, errors.New("no documets found") return nil, errors.New("no documets found")
} else { } else {
return user, nil return user, nil
} }

View File

@ -19,7 +19,7 @@ func (p *provider) AddVerificationRequest(ctx context.Context, verificationReque
verificationRequest.UpdatedAt = time.Now().Unix() verificationRequest.UpdatedAt = time.Now().Unix()
err := collection.Put(verificationRequest).RunWithContext(ctx) err := collection.Put(verificationRequest).RunWithContext(ctx)
if err != nil { if err != nil {
return verificationRequest, err return nil, err
} }
} }
return verificationRequest, nil return verificationRequest, nil
@ -35,7 +35,7 @@ func (p *provider) GetVerificationRequestByToken(ctx context.Context, token stri
} }
err := iter.Err() err := iter.Err()
if err != nil { if err != nil {
return verificationRequest, err return nil, err
} }
return verificationRequest, nil return verificationRequest, nil
} }
@ -50,7 +50,7 @@ func (p *provider) GetVerificationRequestByEmail(ctx context.Context, email stri
} }
err := iter.Err() err := iter.Err()
if err != nil { if err != nil {
return verificationRequest, err return nil, err
} }
return verificationRequest, nil return verificationRequest, nil
} }

View File

@ -91,7 +91,7 @@ func (p *provider) GetWebhookByID(ctx context.Context, webhookID string) (*model
return nil, err return nil, err
} }
if webhook.ID == "" { if webhook.ID == "" {
return webhook.AsAPIWebhook(), errors.New("no documets found") return nil, errors.New("no documets found")
} }
return webhook.AsAPIWebhook(), nil return webhook.AsAPIWebhook(), nil
} }

View File

@ -26,7 +26,7 @@ func (p *provider) AddAuthenticator(ctx context.Context, authenticators *models.
authenticatorsCollection := p.db.Collection(models.Collections.Authenticators, options.Collection()) authenticatorsCollection := p.db.Collection(models.Collections.Authenticators, options.Collection())
_, err := authenticatorsCollection.InsertOne(ctx, authenticators) _, err := authenticatorsCollection.InsertOne(ctx, authenticators)
if err != nil { if err != nil {
return authenticators, err return nil, err
} }
return authenticators, nil return authenticators, nil
} }
@ -36,7 +36,7 @@ func (p *provider) UpdateAuthenticator(ctx context.Context, authenticators *mode
authenticatorsCollection := p.db.Collection(models.Collections.Authenticators, options.Collection()) authenticatorsCollection := p.db.Collection(models.Collections.Authenticators, options.Collection())
_, err := authenticatorsCollection.UpdateOne(ctx, bson.M{"_id": bson.M{"$eq": authenticators.ID}}, bson.M{"$set": authenticators}) _, err := authenticatorsCollection.UpdateOne(ctx, bson.M{"_id": bson.M{"$eq": authenticators.ID}}, bson.M{"$set": authenticators})
if err != nil { if err != nil {
return authenticators, err return nil, err
} }
return authenticators, nil return authenticators, nil
} }
@ -46,7 +46,7 @@ func (p *provider) GetAuthenticatorDetailsByUserId(ctx context.Context, userId s
authenticatorsCollection := p.db.Collection(models.Collections.Authenticators, options.Collection()) authenticatorsCollection := p.db.Collection(models.Collections.Authenticators, options.Collection())
err := authenticatorsCollection.FindOne(ctx, bson.M{"user_id": userId, "method": authenticatorType}).Decode(&authenticators) err := authenticatorsCollection.FindOne(ctx, bson.M{"user_id": userId, "method": authenticatorType}).Decode(&authenticators)
if err != nil { if err != nil {
return authenticators, err return nil, err
} }
return authenticators, nil return authenticators, nil
} }

View File

@ -22,7 +22,7 @@ func (p *provider) AddEnv(ctx context.Context, env *models.Env) (*models.Env, er
configCollection := p.db.Collection(models.Collections.Env, options.Collection()) configCollection := p.db.Collection(models.Collections.Env, options.Collection())
_, err := configCollection.InsertOne(ctx, env) _, err := configCollection.InsertOne(ctx, env)
if err != nil { if err != nil {
return env, err return nil, err
} }
return env, nil return env, nil
} }
@ -33,7 +33,7 @@ func (p *provider) UpdateEnv(ctx context.Context, env *models.Env) (*models.Env,
configCollection := p.db.Collection(models.Collections.Env, options.Collection()) configCollection := p.db.Collection(models.Collections.Env, options.Collection())
_, err := configCollection.UpdateOne(ctx, bson.M{"_id": bson.M{"$eq": env.ID}}, bson.M{"$set": env}, options.MergeUpdateOptions()) _, err := configCollection.UpdateOne(ctx, bson.M{"_id": bson.M{"$eq": env.ID}}, bson.M{"$set": env}, options.MergeUpdateOptions())
if err != nil { if err != nil {
return env, err return nil, err
} }
return env, nil return env, nil
} }
@ -44,13 +44,13 @@ func (p *provider) GetEnv(ctx context.Context) (*models.Env, error) {
configCollection := p.db.Collection(models.Collections.Env, options.Collection()) configCollection := p.db.Collection(models.Collections.Env, options.Collection())
cursor, err := configCollection.Find(ctx, bson.M{}, options.Find()) cursor, err := configCollection.Find(ctx, bson.M{}, options.Find())
if err != nil { if err != nil {
return env, err return nil, err
} }
defer cursor.Close(ctx) defer cursor.Close(ctx)
for cursor.Next(nil) { for cursor.Next(nil) {
err := cursor.Decode(&env) err := cursor.Decode(&env)
if err != nil { if err != nil {
return env, err return nil, err
} }
} }
if env == nil { if env == nil {

View File

@ -2,12 +2,15 @@ package mongodb
import ( import (
"context" "context"
"fmt"
"strings"
"time" "time"
"github.com/authorizerdev/authorizer/server/constants" "github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/db/models" "github.com/authorizerdev/authorizer/server/db/models"
"github.com/authorizerdev/authorizer/server/graph/model" "github.com/authorizerdev/authorizer/server/graph/model"
"github.com/authorizerdev/authorizer/server/memorystore" "github.com/authorizerdev/authorizer/server/memorystore"
"github.com/authorizerdev/authorizer/server/refs"
"github.com/google/uuid" "github.com/google/uuid"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson"
@ -23,17 +26,26 @@ func (p *provider) AddUser(ctx context.Context, user *models.User) (*models.User
if user.Roles == "" { if user.Roles == "" {
defaultRoles, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyDefaultRoles) defaultRoles, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyDefaultRoles)
if err != nil { if err != nil {
return user, err return nil, err
} }
user.Roles = defaultRoles user.Roles = defaultRoles
} }
if user.PhoneNumber != nil && strings.TrimSpace(refs.StringValue(user.PhoneNumber)) != "" {
if u, _ := p.GetUserByPhoneNumber(ctx, refs.StringValue(user.PhoneNumber)); u != nil && u.ID != user.ID {
return user, fmt.Errorf("user with given phone number already exists")
}
} else if user.Email != nil && strings.TrimSpace(refs.StringValue(user.Email)) != "" {
if u, _ := p.GetUserByEmail(ctx, refs.StringValue(user.Email)); u != nil && u.ID != user.ID {
return user, fmt.Errorf("user with given email already exists")
}
}
user.CreatedAt = time.Now().Unix() user.CreatedAt = time.Now().Unix()
user.UpdatedAt = time.Now().Unix() user.UpdatedAt = time.Now().Unix()
user.Key = user.ID user.Key = user.ID
userCollection := p.db.Collection(models.Collections.User, options.Collection()) userCollection := p.db.Collection(models.Collections.User, options.Collection())
_, err := userCollection.InsertOne(ctx, user) _, err := userCollection.InsertOne(ctx, user)
if err != nil { if err != nil {
return user, err return nil, err
} }
return user, nil return user, nil
} }
@ -44,7 +56,7 @@ func (p *provider) UpdateUser(ctx context.Context, user *models.User) (*models.U
userCollection := p.db.Collection(models.Collections.User, options.Collection()) userCollection := p.db.Collection(models.Collections.User, options.Collection())
_, err := userCollection.UpdateOne(ctx, bson.M{"_id": bson.M{"$eq": user.ID}}, bson.M{"$set": user}, options.MergeUpdateOptions()) _, err := userCollection.UpdateOne(ctx, bson.M{"_id": bson.M{"$eq": user.ID}}, bson.M{"$set": user}, options.MergeUpdateOptions())
if err != nil { if err != nil {
return user, err return nil, err
} }
return user, nil return user, nil
} }
@ -103,7 +115,7 @@ func (p *provider) GetUserByEmail(ctx context.Context, email string) (*models.Us
userCollection := p.db.Collection(models.Collections.User, options.Collection()) userCollection := p.db.Collection(models.Collections.User, options.Collection())
err := userCollection.FindOne(ctx, bson.M{"email": email}).Decode(&user) err := userCollection.FindOne(ctx, bson.M{"email": email}).Decode(&user)
if err != nil { if err != nil {
return user, err return nil, err
} }
return user, nil return user, nil
} }
@ -114,7 +126,7 @@ func (p *provider) GetUserByID(ctx context.Context, id string) (*models.User, er
userCollection := p.db.Collection(models.Collections.User, options.Collection()) userCollection := p.db.Collection(models.Collections.User, options.Collection())
err := userCollection.FindOne(ctx, bson.M{"_id": id}).Decode(&user) err := userCollection.FindOne(ctx, bson.M{"_id": id}).Decode(&user)
if err != nil { if err != nil {
return user, err return nil, err
} }
return user, nil return user, nil
} }

View File

@ -22,7 +22,7 @@ func (p *provider) AddVerificationRequest(ctx context.Context, verificationReque
verificationRequestCollection := p.db.Collection(models.Collections.VerificationRequest, options.Collection()) verificationRequestCollection := p.db.Collection(models.Collections.VerificationRequest, options.Collection())
_, err := verificationRequestCollection.InsertOne(ctx, verificationRequest) _, err := verificationRequestCollection.InsertOne(ctx, verificationRequest)
if err != nil { if err != nil {
return verificationRequest, err return nil, err
} }
} }
@ -36,7 +36,7 @@ func (p *provider) GetVerificationRequestByToken(ctx context.Context, token stri
verificationRequestCollection := p.db.Collection(models.Collections.VerificationRequest, options.Collection()) verificationRequestCollection := p.db.Collection(models.Collections.VerificationRequest, options.Collection())
err := verificationRequestCollection.FindOne(ctx, bson.M{"token": token}).Decode(&verificationRequest) err := verificationRequestCollection.FindOne(ctx, bson.M{"token": token}).Decode(&verificationRequest)
if err != nil { if err != nil {
return verificationRequest, err return nil, err
} }
return verificationRequest, nil return verificationRequest, nil
@ -49,7 +49,7 @@ func (p *provider) GetVerificationRequestByEmail(ctx context.Context, email stri
verificationRequestCollection := p.db.Collection(models.Collections.VerificationRequest, options.Collection()) verificationRequestCollection := p.db.Collection(models.Collections.VerificationRequest, options.Collection())
err := verificationRequestCollection.FindOne(ctx, bson.M{"email": email, "identifier": identifier}).Decode(&verificationRequest) err := verificationRequestCollection.FindOne(ctx, bson.M{"email": email, "identifier": identifier}).Decode(&verificationRequest)
if err != nil { if err != nil {
return verificationRequest, err return nil, err
} }
return verificationRequest, nil return verificationRequest, nil

View File

@ -2,12 +2,15 @@ package provider_template
import ( import (
"context" "context"
"fmt"
"strings"
"time" "time"
"github.com/authorizerdev/authorizer/server/constants" "github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/db/models" "github.com/authorizerdev/authorizer/server/db/models"
"github.com/authorizerdev/authorizer/server/graph/model" "github.com/authorizerdev/authorizer/server/graph/model"
"github.com/authorizerdev/authorizer/server/memorystore" "github.com/authorizerdev/authorizer/server/memorystore"
"github.com/authorizerdev/authorizer/server/refs"
"github.com/google/uuid" "github.com/google/uuid"
) )
@ -19,10 +22,19 @@ func (p *provider) AddUser(ctx context.Context, user *models.User) (*models.User
if user.Roles == "" { if user.Roles == "" {
defaultRoles, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyDefaultRoles) defaultRoles, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyDefaultRoles)
if err != nil { if err != nil {
return user, err return nil, err
} }
user.Roles = defaultRoles user.Roles = defaultRoles
} }
if user.PhoneNumber != nil && strings.TrimSpace(refs.StringValue(user.PhoneNumber)) != "" {
if u, _ := p.GetUserByPhoneNumber(ctx, refs.StringValue(user.PhoneNumber)); u != nil && u.ID != user.ID {
return user, fmt.Errorf("user with given phone number already exists")
}
} else if user.Email != nil && strings.TrimSpace(refs.StringValue(user.Email)) != "" {
if u, _ := p.GetUserByEmail(ctx, refs.StringValue(user.Email)); u != nil && u.ID != user.ID {
return user, fmt.Errorf("user with given email already exists")
}
}
user.CreatedAt = time.Now().Unix() user.CreatedAt = time.Now().Unix()
user.UpdatedAt = time.Now().Unix() user.UpdatedAt = time.Now().Unix()
return user, nil return user, nil

View File

@ -7,33 +7,56 @@ import (
"github.com/authorizerdev/authorizer/server/db/models" "github.com/authorizerdev/authorizer/server/db/models"
"github.com/google/uuid" "github.com/google/uuid"
"gorm.io/gorm/clause"
) )
// UpsertOTP to add or update otp // UpsertOTP to add or update otp
func (p *provider) UpsertOTP(ctx context.Context, otp *models.OTP) (*models.OTP, error) { func (p *provider) UpsertOTP(ctx context.Context, otpParam *models.OTP) (*models.OTP, error) {
if otp.ID == "" { if otpParam.ID == "" {
otp.ID = uuid.New().String() otpParam.ID = uuid.New().String()
} }
// check if email or phone number is present // check if email or phone number is present
if otp.Email == "" && otp.PhoneNumber == "" { if otpParam.Email == "" && otpParam.PhoneNumber == "" {
return nil, errors.New("email or phone_number is required") return nil, errors.New("email or phone_number is required")
} }
uniqueField := models.FieldNameEmail uniqueField := models.FieldNameEmail
if otp.Email == "" && otp.PhoneNumber != "" { if otpParam.Email == "" && otpParam.PhoneNumber != "" {
uniqueField = models.FieldNamePhoneNumber uniqueField = models.FieldNamePhoneNumber
} }
otp.Key = otp.ID var otp *models.OTP
otp.CreatedAt = time.Now().Unix() if uniqueField == models.FieldNameEmail {
otp.UpdatedAt = time.Now().Unix() otp, _ = p.GetOTPByEmail(ctx, otpParam.Email)
res := p.db.Clauses(clause.OnConflict{ } else {
Columns: []clause.Column{{Name: uniqueField}}, otp, _ = p.GetOTPByPhoneNumber(ctx, otpParam.PhoneNumber)
DoUpdates: clause.AssignmentColumns([]string{"otp", "expires_at", "updated_at"}), }
}).Create(&otp) shouldCreate := false
if res.Error != nil { if otp == nil {
return nil, res.Error id := uuid.NewString()
otp = &models.OTP{
ID: id,
Key: id,
Otp: otpParam.Otp,
Email: otpParam.Email,
PhoneNumber: otpParam.PhoneNumber,
ExpiresAt: otpParam.ExpiresAt,
CreatedAt: time.Now().Unix(),
}
shouldCreate = true
} else {
otp.Otp = otpParam.Otp
otp.ExpiresAt = otpParam.ExpiresAt
}
otp.UpdatedAt = time.Now().Unix()
if shouldCreate {
result := p.db.Create(&otp)
if result.Error != nil {
return nil, result.Error
}
} else {
result := p.db.Save(&otp)
if result.Error != nil {
return nil, result.Error
}
} }
return otp, nil return otp, nil
} }

View File

@ -13,7 +13,6 @@ import (
"github.com/authorizerdev/authorizer/server/refs" "github.com/authorizerdev/authorizer/server/refs"
"github.com/google/uuid" "github.com/google/uuid"
"gorm.io/gorm" "gorm.io/gorm"
"gorm.io/gorm/clause"
) )
// AddUser to save user information in database // AddUser to save user information in database
@ -25,25 +24,25 @@ func (p *provider) AddUser(ctx context.Context, user *models.User) (*models.User
if user.Roles == "" { if user.Roles == "" {
defaultRoles, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyDefaultRoles) defaultRoles, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyDefaultRoles)
if err != nil { if err != nil {
return user, err return nil, err
} }
user.Roles = defaultRoles user.Roles = defaultRoles
} }
if user.PhoneNumber != nil && strings.TrimSpace(refs.StringValue(user.PhoneNumber)) != "" { if user.PhoneNumber != nil && strings.TrimSpace(refs.StringValue(user.PhoneNumber)) != "" {
if u, _ := p.GetUserByPhoneNumber(ctx, refs.StringValue(user.PhoneNumber)); u != nil { if u, _ := p.GetUserByPhoneNumber(ctx, refs.StringValue(user.PhoneNumber)); u != nil && u.ID != user.ID {
return user, fmt.Errorf("user with given phone number already exists") return user, fmt.Errorf("user with given phone number already exists")
} }
} else if user.Email != nil && strings.TrimSpace(refs.StringValue(user.Email)) != "" {
if u, _ := p.GetUserByEmail(ctx, refs.StringValue(user.Email)); u != nil && u.ID != user.ID {
return user, fmt.Errorf("user with given email already exists")
}
} }
user.CreatedAt = time.Now().Unix() user.CreatedAt = time.Now().Unix()
user.UpdatedAt = time.Now().Unix() user.UpdatedAt = time.Now().Unix()
user.Key = user.ID user.Key = user.ID
result := p.db.Clauses( result := p.db.Create(&user)
clause.OnConflict{
UpdateAll: true,
Columns: []clause.Column{{Name: "email"}},
}).Create(&user)
if result.Error != nil { if result.Error != nil {
return user, result.Error return user, result.Error
@ -113,7 +112,7 @@ func (p *provider) GetUserByEmail(ctx context.Context, email string) (*models.Us
var user *models.User var user *models.User
result := p.db.Where("email = ?", email).First(&user) result := p.db.Where("email = ?", email).First(&user)
if result.Error != nil { if result.Error != nil {
return user, result.Error return nil, result.Error
} }
return user, nil return user, nil
} }
@ -123,7 +122,7 @@ func (p *provider) GetUserByID(ctx context.Context, id string) (*models.User, er
var user *models.User var user *models.User
result := p.db.Where("id = ?", id).First(&user) result := p.db.Where("id = ?", id).First(&user)
if result.Error != nil { if result.Error != nil {
return user, result.Error return nil, result.Error
} }
return user, nil return user, nil
} }

View File

@ -53,13 +53,13 @@ const (
<table width="100%%" cellspacing="0" cellpadding="0"> <table width="100%%" cellspacing="0" cellpadding="0">
<tbody> <tbody>
<tr> <tr>
<td class="esd-block-image es-m-txt-c es-p5b" style="font-size:0;padding:10px" align="center"><a target="_blank" clicktracking="off"><img src="{{.org_logo}}" alt="icon" style="display: block;" title="icon" width="30"></a></td> <td class="esd-block-image es-m-txt-c es-p5b" style="font-size:0;padding:10px" align="center"><a target="_blank" clicktracking="off"><img src="{{.organization.logo}}" alt="icon" style="display: block;" title="icon" width="30"></a></td>
</tr> </tr>
<tr style="background: rgb(249,250,251);padding: 10px;margin-bottom:10px;border-radius:5px;"> <tr style="background: rgb(249,250,251);padding: 10px;margin-bottom:10px;border-radius:5px;">
<td class="esd-block-text es-m-txt-c es-p15t" align="center" style="padding:10px;padding-bottom:30px;"> <td class="esd-block-text es-m-txt-c es-p15t" align="center" style="padding:10px;padding-bottom:30px;">
<p>Hey there 👋</p> <p>Hey there 👋</p>
<p>We have received request to verify email for <b>{{.org_name}}</b>. If this is correct, please confirm your email address by clicking the button below.</p> <br/> <p>We have received request to verify email for <b>{{.organization.name}}</b>. If this is correct, please confirm your email address by clicking the button below.</p> <br/>
<a <a
clicktracking="off" href="{{.verification_url}}" class="es-button" target="_blank" style="text-decoration: none;padding:10px 15px;background-color: rgba(59,130,246,1);color: #fff;font-size: 1em;border-radius:5px;">Confirm Email</a> clicktracking="off" href="{{.verification_url}}" class="es-button" target="_blank" style="text-decoration: none;padding:10px 15px;background-color: rgba(59,130,246,1);color: #fff;font-size: 1em;border-radius:5px;">Confirm Email</a>
</td> </td>

View File

@ -103,6 +103,7 @@ type ComplexityRoot struct {
DisableLoginPage func(childComplexity int) int DisableLoginPage func(childComplexity int) int
DisableMagicLinkLogin func(childComplexity int) int DisableMagicLinkLogin func(childComplexity int) int
DisableMailOtpLogin func(childComplexity int) int DisableMailOtpLogin func(childComplexity int) int
DisableMobileBasicAuthentication func(childComplexity int) int
DisableMultiFactorAuthentication func(childComplexity int) int DisableMultiFactorAuthentication func(childComplexity int) int
DisablePlayground func(childComplexity int) int DisablePlayground func(childComplexity int) int
DisableRedisForEnv func(childComplexity int) int DisableRedisForEnv func(childComplexity int) int
@ -755,6 +756,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.Env.DisableMailOtpLogin(childComplexity), true return e.complexity.Env.DisableMailOtpLogin(childComplexity), true
case "Env.DISABLE_MOBILE_BASIC_AUTHENTICATION":
if e.complexity.Env.DisableMobileBasicAuthentication == nil {
break
}
return e.complexity.Env.DisableMobileBasicAuthentication(childComplexity), true
case "Env.DISABLE_MULTI_FACTOR_AUTHENTICATION": case "Env.DISABLE_MULTI_FACTOR_AUTHENTICATION":
if e.complexity.Env.DisableMultiFactorAuthentication == nil { if e.complexity.Env.DisableMultiFactorAuthentication == nil {
break break
@ -2557,6 +2565,7 @@ type Env {
RESET_PASSWORD_URL: String RESET_PASSWORD_URL: String
DISABLE_EMAIL_VERIFICATION: Boolean! DISABLE_EMAIL_VERIFICATION: Boolean!
DISABLE_BASIC_AUTHENTICATION: Boolean! DISABLE_BASIC_AUTHENTICATION: Boolean!
DISABLE_MOBILE_BASIC_AUTHENTICATION: Boolean!
DISABLE_MAGIC_LINK_LOGIN: Boolean! DISABLE_MAGIC_LINK_LOGIN: Boolean!
DISABLE_LOGIN_PAGE: Boolean! DISABLE_LOGIN_PAGE: Boolean!
DISABLE_SIGN_UP: Boolean! DISABLE_SIGN_UP: Boolean!
@ -2688,6 +2697,7 @@ input UpdateEnvInput {
ADMIN_COOKIE_SECURE: Boolean ADMIN_COOKIE_SECURE: Boolean
DISABLE_EMAIL_VERIFICATION: Boolean DISABLE_EMAIL_VERIFICATION: Boolean
DISABLE_BASIC_AUTHENTICATION: Boolean DISABLE_BASIC_AUTHENTICATION: Boolean
DISABLE_MOBILE_BASIC_AUTHENTICATION: Boolean
DISABLE_MAGIC_LINK_LOGIN: Boolean DISABLE_MAGIC_LINK_LOGIN: Boolean
DISABLE_LOGIN_PAGE: Boolean DISABLE_LOGIN_PAGE: Boolean
DISABLE_SIGN_UP: Boolean DISABLE_SIGN_UP: Boolean
@ -2851,6 +2861,7 @@ input UpdateUserInput {
gender: String gender: String
birthdate: String birthdate: String
phone_number: String phone_number: String
phone_number_verified: Boolean
picture: String picture: String
roles: [String] roles: [String]
is_multi_factor_auth_enabled: Boolean is_multi_factor_auth_enabled: Boolean
@ -5879,6 +5890,50 @@ func (ec *executionContext) fieldContext_Env_DISABLE_BASIC_AUTHENTICATION(ctx co
return fc, nil return fc, nil
} }
func (ec *executionContext) _Env_DISABLE_MOBILE_BASIC_AUTHENTICATION(ctx context.Context, field graphql.CollectedField, obj *model.Env) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_Env_DISABLE_MOBILE_BASIC_AUTHENTICATION(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.DisableMobileBasicAuthentication, 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.(bool)
fc.Result = res
return ec.marshalNBoolean2bool(ctx, field.Selections, res)
}
func (ec *executionContext) fieldContext_Env_DISABLE_MOBILE_BASIC_AUTHENTICATION(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 Boolean does not have child fields")
},
}
return fc, nil
}
func (ec *executionContext) _Env_DISABLE_MAGIC_LINK_LOGIN(ctx context.Context, field graphql.CollectedField, obj *model.Env) (ret graphql.Marshaler) { func (ec *executionContext) _Env_DISABLE_MAGIC_LINK_LOGIN(ctx context.Context, field graphql.CollectedField, obj *model.Env) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_Env_DISABLE_MAGIC_LINK_LOGIN(ctx, field) fc, err := ec.fieldContext_Env_DISABLE_MAGIC_LINK_LOGIN(ctx, field)
if err != nil { if err != nil {
@ -11783,6 +11838,8 @@ func (ec *executionContext) fieldContext_Query__env(ctx context.Context, field g
return ec.fieldContext_Env_DISABLE_EMAIL_VERIFICATION(ctx, field) return ec.fieldContext_Env_DISABLE_EMAIL_VERIFICATION(ctx, field)
case "DISABLE_BASIC_AUTHENTICATION": case "DISABLE_BASIC_AUTHENTICATION":
return ec.fieldContext_Env_DISABLE_BASIC_AUTHENTICATION(ctx, field) return ec.fieldContext_Env_DISABLE_BASIC_AUTHENTICATION(ctx, field)
case "DISABLE_MOBILE_BASIC_AUTHENTICATION":
return ec.fieldContext_Env_DISABLE_MOBILE_BASIC_AUTHENTICATION(ctx, field)
case "DISABLE_MAGIC_LINK_LOGIN": case "DISABLE_MAGIC_LINK_LOGIN":
return ec.fieldContext_Env_DISABLE_MAGIC_LINK_LOGIN(ctx, field) return ec.fieldContext_Env_DISABLE_MAGIC_LINK_LOGIN(ctx, field)
case "DISABLE_LOGIN_PAGE": case "DISABLE_LOGIN_PAGE":
@ -18377,7 +18434,7 @@ func (ec *executionContext) unmarshalInputUpdateEnvInput(ctx context.Context, ob
asMap[k] = v 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", "SMTP_LOCAL_NAME", "SENDER_EMAIL", "SENDER_NAME", "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", "DISCORD_CLIENT_ID", "DISCORD_CLIENT_SECRET", "TWITTER_CLIENT_ID", "TWITTER_CLIENT_SECRET", "MICROSOFT_CLIENT_ID", "MICROSOFT_CLIENT_SECRET", "MICROSOFT_ACTIVE_DIRECTORY_TENANT_ID", "TWITCH_CLIENT_ID", "TWITCH_CLIENT_SECRET", "ORGANIZATION_NAME", "ORGANIZATION_LOGO", "DEFAULT_AUTHORIZE_RESPONSE_TYPE", "DEFAULT_AUTHORIZE_RESPONSE_MODE", "DISABLE_PLAYGROUND", "DISABLE_MAIL_OTP_LOGIN", "DISABLE_TOTP_LOGIN"} 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", "SENDER_NAME", "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_MOBILE_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", "DISCORD_CLIENT_ID", "DISCORD_CLIENT_SECRET", "TWITTER_CLIENT_ID", "TWITTER_CLIENT_SECRET", "MICROSOFT_CLIENT_ID", "MICROSOFT_CLIENT_SECRET", "MICROSOFT_ACTIVE_DIRECTORY_TENANT_ID", "TWITCH_CLIENT_ID", "TWITCH_CLIENT_SECRET", "ORGANIZATION_NAME", "ORGANIZATION_LOGO", "DEFAULT_AUTHORIZE_RESPONSE_TYPE", "DEFAULT_AUTHORIZE_RESPONSE_MODE", "DISABLE_PLAYGROUND", "DISABLE_MAIL_OTP_LOGIN", "DISABLE_TOTP_LOGIN"}
for _, k := range fieldsInOrder { for _, k := range fieldsInOrder {
v, ok := asMap[k] v, ok := asMap[k]
if !ok { if !ok {
@ -18582,6 +18639,15 @@ func (ec *executionContext) unmarshalInputUpdateEnvInput(ctx context.Context, ob
return it, err return it, err
} }
it.DisableBasicAuthentication = data it.DisableBasicAuthentication = data
case "DISABLE_MOBILE_BASIC_AUTHENTICATION":
var err error
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("DISABLE_MOBILE_BASIC_AUTHENTICATION"))
data, err := ec.unmarshalOBoolean2ᚖbool(ctx, v)
if err != nil {
return it, err
}
it.DisableMobileBasicAuthentication = data
case "DISABLE_MAGIC_LINK_LOGIN": case "DISABLE_MAGIC_LINK_LOGIN":
var err error var err error
@ -19074,7 +19140,7 @@ func (ec *executionContext) unmarshalInputUpdateUserInput(ctx context.Context, o
asMap[k] = v asMap[k] = v
} }
fieldsInOrder := [...]string{"id", "email", "email_verified", "given_name", "family_name", "middle_name", "nickname", "gender", "birthdate", "phone_number", "picture", "roles", "is_multi_factor_auth_enabled", "app_data"} fieldsInOrder := [...]string{"id", "email", "email_verified", "given_name", "family_name", "middle_name", "nickname", "gender", "birthdate", "phone_number", "phone_number_verified", "picture", "roles", "is_multi_factor_auth_enabled", "app_data"}
for _, k := range fieldsInOrder { for _, k := range fieldsInOrder {
v, ok := asMap[k] v, ok := asMap[k]
if !ok { if !ok {
@ -19171,6 +19237,15 @@ func (ec *executionContext) unmarshalInputUpdateUserInput(ctx context.Context, o
return it, err return it, err
} }
it.PhoneNumber = data it.PhoneNumber = data
case "phone_number_verified":
var err error
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("phone_number_verified"))
data, err := ec.unmarshalOBoolean2ᚖbool(ctx, v)
if err != nil {
return it, err
}
it.PhoneNumberVerified = data
case "picture": case "picture":
var err error var err error
@ -19761,6 +19836,11 @@ func (ec *executionContext) _Env(ctx context.Context, sel ast.SelectionSet, obj
if out.Values[i] == graphql.Null { if out.Values[i] == graphql.Null {
out.Invalids++ out.Invalids++
} }
case "DISABLE_MOBILE_BASIC_AUTHENTICATION":
out.Values[i] = ec._Env_DISABLE_MOBILE_BASIC_AUTHENTICATION(ctx, field, obj)
if out.Values[i] == graphql.Null {
out.Invalids++
}
case "DISABLE_MAGIC_LINK_LOGIN": case "DISABLE_MAGIC_LINK_LOGIN":
out.Values[i] = ec._Env_DISABLE_MAGIC_LINK_LOGIN(ctx, field, obj) out.Values[i] = ec._Env_DISABLE_MAGIC_LINK_LOGIN(ctx, field, obj)
if out.Values[i] == graphql.Null { if out.Values[i] == graphql.Null {

View File

@ -93,6 +93,7 @@ type Env struct {
ResetPasswordURL *string `json:"RESET_PASSWORD_URL,omitempty"` ResetPasswordURL *string `json:"RESET_PASSWORD_URL,omitempty"`
DisableEmailVerification bool `json:"DISABLE_EMAIL_VERIFICATION"` DisableEmailVerification bool `json:"DISABLE_EMAIL_VERIFICATION"`
DisableBasicAuthentication bool `json:"DISABLE_BASIC_AUTHENTICATION"` DisableBasicAuthentication bool `json:"DISABLE_BASIC_AUTHENTICATION"`
DisableMobileBasicAuthentication bool `json:"DISABLE_MOBILE_BASIC_AUTHENTICATION"`
DisableMagicLinkLogin bool `json:"DISABLE_MAGIC_LINK_LOGIN"` DisableMagicLinkLogin bool `json:"DISABLE_MAGIC_LINK_LOGIN"`
DisableLoginPage bool `json:"DISABLE_LOGIN_PAGE"` DisableLoginPage bool `json:"DISABLE_LOGIN_PAGE"`
DisableSignUp bool `json:"DISABLE_SIGN_UP"` DisableSignUp bool `json:"DISABLE_SIGN_UP"`
@ -373,6 +374,7 @@ type UpdateEnvInput struct {
AdminCookieSecure *bool `json:"ADMIN_COOKIE_SECURE,omitempty"` AdminCookieSecure *bool `json:"ADMIN_COOKIE_SECURE,omitempty"`
DisableEmailVerification *bool `json:"DISABLE_EMAIL_VERIFICATION,omitempty"` DisableEmailVerification *bool `json:"DISABLE_EMAIL_VERIFICATION,omitempty"`
DisableBasicAuthentication *bool `json:"DISABLE_BASIC_AUTHENTICATION,omitempty"` DisableBasicAuthentication *bool `json:"DISABLE_BASIC_AUTHENTICATION,omitempty"`
DisableMobileBasicAuthentication *bool `json:"DISABLE_MOBILE_BASIC_AUTHENTICATION,omitempty"`
DisableMagicLinkLogin *bool `json:"DISABLE_MAGIC_LINK_LOGIN,omitempty"` DisableMagicLinkLogin *bool `json:"DISABLE_MAGIC_LINK_LOGIN,omitempty"`
DisableLoginPage *bool `json:"DISABLE_LOGIN_PAGE,omitempty"` DisableLoginPage *bool `json:"DISABLE_LOGIN_PAGE,omitempty"`
DisableSignUp *bool `json:"DISABLE_SIGN_UP,omitempty"` DisableSignUp *bool `json:"DISABLE_SIGN_UP,omitempty"`
@ -440,6 +442,7 @@ type UpdateUserInput struct {
Gender *string `json:"gender,omitempty"` Gender *string `json:"gender,omitempty"`
Birthdate *string `json:"birthdate,omitempty"` Birthdate *string `json:"birthdate,omitempty"`
PhoneNumber *string `json:"phone_number,omitempty"` PhoneNumber *string `json:"phone_number,omitempty"`
PhoneNumberVerified *bool `json:"phone_number_verified,omitempty"`
Picture *string `json:"picture,omitempty"` Picture *string `json:"picture,omitempty"`
Roles []*string `json:"roles,omitempty"` Roles []*string `json:"roles,omitempty"`
IsMultiFactorAuthEnabled *bool `json:"is_multi_factor_auth_enabled,omitempty"` IsMultiFactorAuthEnabled *bool `json:"is_multi_factor_auth_enabled,omitempty"`

View File

@ -158,6 +158,7 @@ type Env {
RESET_PASSWORD_URL: String RESET_PASSWORD_URL: String
DISABLE_EMAIL_VERIFICATION: Boolean! DISABLE_EMAIL_VERIFICATION: Boolean!
DISABLE_BASIC_AUTHENTICATION: Boolean! DISABLE_BASIC_AUTHENTICATION: Boolean!
DISABLE_MOBILE_BASIC_AUTHENTICATION: Boolean!
DISABLE_MAGIC_LINK_LOGIN: Boolean! DISABLE_MAGIC_LINK_LOGIN: Boolean!
DISABLE_LOGIN_PAGE: Boolean! DISABLE_LOGIN_PAGE: Boolean!
DISABLE_SIGN_UP: Boolean! DISABLE_SIGN_UP: Boolean!
@ -289,6 +290,7 @@ input UpdateEnvInput {
ADMIN_COOKIE_SECURE: Boolean ADMIN_COOKIE_SECURE: Boolean
DISABLE_EMAIL_VERIFICATION: Boolean DISABLE_EMAIL_VERIFICATION: Boolean
DISABLE_BASIC_AUTHENTICATION: Boolean DISABLE_BASIC_AUTHENTICATION: Boolean
DISABLE_MOBILE_BASIC_AUTHENTICATION: Boolean
DISABLE_MAGIC_LINK_LOGIN: Boolean DISABLE_MAGIC_LINK_LOGIN: Boolean
DISABLE_LOGIN_PAGE: Boolean DISABLE_LOGIN_PAGE: Boolean
DISABLE_SIGN_UP: Boolean DISABLE_SIGN_UP: Boolean
@ -452,6 +454,7 @@ input UpdateUserInput {
gender: String gender: String
birthdate: String birthdate: String
phone_number: String phone_number: String
phone_number_verified: Boolean
picture: String picture: String
roles: [String] roles: [String]
is_multi_factor_auth_enabled: Boolean is_multi_factor_auth_enabled: Boolean

View File

@ -617,7 +617,7 @@ func processAppleUserInfo(ctx context.Context, code string) (*models.User, error
} }
} }
return user, err return nil, err
} }
func processDiscordUserInfo(ctx context.Context, code string) (*models.User, error) { func processDiscordUserInfo(ctx context.Context, code string) (*models.User, error) {

View File

@ -24,9 +24,13 @@ func RevokeRefreshTokenHandler() gin.HandlerFunc {
}) })
return return
} }
// get client ID
clientID := strings.TrimSpace(reqBody["client_id"]) // kept for backward compatibility // else we expect to be present as header
if clientID == "" {
clientID = gc.Request.Header.Get("x-authorizer-client-id")
}
// get fingerprint hash // get fingerprint hash
refreshToken := strings.TrimSpace(reqBody["refresh_token"]) refreshToken := strings.TrimSpace(reqBody["refresh_token"])
clientID := strings.TrimSpace(reqBody["client_id"])
if clientID == "" { if clientID == "" {
log.Debug("Client ID is empty") log.Debug("Client ID is empty")

View File

@ -0,0 +1,29 @@
package middlewares
import (
"net/http"
"github.com/gin-gonic/gin"
log "github.com/sirupsen/logrus"
"github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/memorystore"
)
// ClientCheckMiddleware is a middleware to verify the client ID
// Note: client ID is passed in the header
func ClientCheckMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
clientID := c.Request.Header.Get("X-Authorizer-Client-ID")
if client, _ := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyClientID); clientID != "" && client != "" && client != clientID {
log.Debug("Client ID is invalid: ", clientID)
c.JSON(http.StatusBadRequest, gin.H{
"error": "invalid_client_id",
"error_description": "The client id is invalid",
})
return
}
c.Next()
}
}

View File

@ -14,7 +14,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, X-authorizer-url") 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, X-Forwarded-Proto, X-authorizer-client-id")
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" {

View File

@ -205,6 +205,7 @@ func EnvResolver(ctx context.Context) (*model.Env, error) {
// bool vars // bool vars
res.DisableEmailVerification = store[constants.EnvKeyDisableEmailVerification].(bool) res.DisableEmailVerification = store[constants.EnvKeyDisableEmailVerification].(bool)
res.DisableBasicAuthentication = store[constants.EnvKeyDisableBasicAuthentication].(bool) res.DisableBasicAuthentication = store[constants.EnvKeyDisableBasicAuthentication].(bool)
res.DisableMobileBasicAuthentication = store[constants.EnvKeyDisableMobileBasicAuthentication].(bool)
res.DisableMagicLinkLogin = store[constants.EnvKeyDisableMagicLinkLogin].(bool) res.DisableMagicLinkLogin = store[constants.EnvKeyDisableMagicLinkLogin].(bool)
res.DisableLoginPage = store[constants.EnvKeyDisableLoginPage].(bool) res.DisableLoginPage = store[constants.EnvKeyDisableLoginPage].(bool)
res.DisableSignUp = store[constants.EnvKeyDisableSignUp].(bool) res.DisableSignUp = store[constants.EnvKeyDisableSignUp].(bool)

View File

@ -83,6 +83,39 @@ func LoginResolver(ctx context.Context, params model.LoginInput) (*model.AuthRes
log.Debug("User access is revoked") log.Debug("User access is revoked")
return res, fmt.Errorf(`user access has been revoked`) return res, fmt.Errorf(`user access has been revoked`)
} }
isEmailServiceEnabled, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyIsEmailServiceEnabled)
if err != nil || !isEmailServiceEnabled {
log.Debug("Email service not enabled: ", err)
}
isSMSServiceEnabled, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyIsSMSServiceEnabled)
if err != nil || !isSMSServiceEnabled {
log.Debug("SMS service not enabled: ", err)
}
// If multi factor authentication is enabled and we need to generate OTP for mail / sms based MFA
generateOTP := func(expiresAt int64) (*models.OTP, error) {
otp := utils.GenerateOTP()
otpData, err := db.Provider.UpsertOTP(ctx, &models.OTP{
Email: refs.StringValue(user.Email),
PhoneNumber: refs.StringValue(user.PhoneNumber),
Otp: otp,
ExpiresAt: expiresAt,
})
if err != nil {
log.Debug("Failed to add otp: ", err)
return nil, err
}
return otpData, nil
}
setOTPMFaSession := func(expiresAt int64) error {
mfaSession := uuid.NewString()
err = memorystore.Provider.SetMfaSession(user.ID, mfaSession, expiresAt)
if err != nil {
log.Debug("Failed to add mfasession: ", err)
return err
}
cookie.SetMfaSession(gc, mfaSession)
return nil
}
if isEmailLogin { if isEmailLogin {
if !strings.Contains(user.SignupMethods, constants.AuthRecipeMethodBasicAuth) { if !strings.Contains(user.SignupMethods, constants.AuthRecipeMethodBasicAuth) {
log.Debug("User signup method is not basic auth") log.Debug("User signup method is not basic auth")
@ -90,8 +123,38 @@ func LoginResolver(ctx context.Context, params model.LoginInput) (*model.AuthRes
} }
if user.EmailVerifiedAt == nil { if user.EmailVerifiedAt == nil {
log.Debug("User email is not verified") // Check if email service is enabled
// Send email verification via otp
if !isEmailServiceEnabled {
log.Debug("User email is not verified and email service is not enabled")
return res, fmt.Errorf(`email not verified`) return res, fmt.Errorf(`email not verified`)
} else {
expiresAt := time.Now().Add(1 * time.Minute).Unix()
otpData, err := generateOTP(expiresAt)
if err != nil {
log.Debug("Failed to generate otp: ", err)
return nil, err
}
if err := setOTPMFaSession(expiresAt); err != nil {
log.Debug("Failed to set mfa session: ", err)
return nil, err
}
go func() {
// exec it as go routine so that we can reduce the api latency
if err := mailService.SendEmail([]string{email}, constants.VerificationTypeOTP, map[string]interface{}{
"user": user.ToMap(),
"organization": utils.GetOrganization(),
"otp": otpData.Otp,
}); err != nil {
log.Debug("Failed to send otp email: ", err)
}
utils.RegisterEvent(ctx, constants.UserLoginWebhookEvent, constants.AuthRecipeMethodBasicAuth, user)
}()
return &model.AuthResponse{
Message: "Please check email inbox for the OTP",
ShouldShowEmailOtpScreen: refs.NewBoolRef(isMobileLogin),
}, nil
}
} }
} else { } else {
if !strings.Contains(user.SignupMethods, constants.AuthRecipeMethodMobileBasicAuth) { if !strings.Contains(user.SignupMethods, constants.AuthRecipeMethodMobileBasicAuth) {
@ -100,8 +163,34 @@ func LoginResolver(ctx context.Context, params model.LoginInput) (*model.AuthRes
} }
if user.PhoneNumberVerifiedAt == nil { if user.PhoneNumberVerifiedAt == nil {
if !isSMSServiceEnabled {
log.Debug("User phone number is not verified") log.Debug("User phone number is not verified")
return res, fmt.Errorf(`phone number is not verified`) return res, fmt.Errorf(`phone number is not verified and sms service is not enabled`)
} else {
expiresAt := time.Now().Add(1 * time.Minute).Unix()
otpData, err := generateOTP(expiresAt)
if err != nil {
log.Debug("Failed to generate otp: ", err)
return nil, err
}
if err := setOTPMFaSession(expiresAt); err != nil {
log.Debug("Failed to set mfa session: ", err)
return nil, err
}
go func() {
smsBody := strings.Builder{}
smsBody.WriteString("Your verification code is: ")
smsBody.WriteString(otpData.Otp)
utils.RegisterEvent(ctx, constants.UserLoginWebhookEvent, constants.AuthRecipeMethodMobileBasicAuth, user)
if err := smsproviders.SendSMS(phoneNumber, smsBody.String()); err != nil {
log.Debug("Failed to send sms: ", err)
}
}()
return &model.AuthResponse{
Message: "Please check text message for the OTP",
ShouldShowMobileOtpScreen: refs.NewBoolRef(isMobileLogin),
}, nil
}
} }
} }
err = crypto.VerifyPassword(*user.Password, params.Password) err = crypto.VerifyPassword(*user.Password, params.Password)
@ -129,14 +218,6 @@ func LoginResolver(ctx context.Context, params model.LoginInput) (*model.AuthRes
if params.Scope != nil && len(scope) > 0 { if params.Scope != nil && len(scope) > 0 {
scope = params.Scope scope = params.Scope
} }
isEmailServiceEnabled, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyIsEmailServiceEnabled)
if err != nil || !isEmailServiceEnabled {
log.Debug("Email service not enabled: ", err)
}
isSMSServiceEnabled, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyIsSMSServiceEnabled)
if err != nil || !isSMSServiceEnabled {
log.Debug("SMS service not enabled: ", err)
}
isMFADisabled, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyDisableMultiFactorAuthentication) isMFADisabled, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyDisableMultiFactorAuthentication)
if err != nil || !isMFADisabled { if err != nil || !isMFADisabled {
@ -157,44 +238,20 @@ func LoginResolver(ctx context.Context, params model.LoginInput) (*model.AuthRes
if err != nil || !isSMSOTPDisabled { if err != nil || !isSMSOTPDisabled {
log.Debug("sms OTP service not enabled: ", err) log.Debug("sms OTP service not enabled: ", err)
} }
setOTPMFaSession := func(expiresAt int64) error {
mfaSession := uuid.NewString()
err = memorystore.Provider.SetMfaSession(user.ID, mfaSession, expiresAt)
if err != nil {
log.Debug("Failed to add mfasession: ", err)
return err
}
cookie.SetMfaSession(gc, mfaSession)
return nil
}
// If multi factor authentication is enabled and we need to generate OTP for mail / sms based MFA
generateOTP := func(expiresAt int64) (*models.OTP, error) {
otp := utils.GenerateOTP()
otpData, err := db.Provider.UpsertOTP(ctx, &models.OTP{
Email: refs.StringValue(user.Email),
PhoneNumber: refs.StringValue(user.PhoneNumber),
Otp: otp,
ExpiresAt: expiresAt,
})
if err != nil {
log.Debug("Failed to add otp: ", err)
return nil, err
}
return otpData, nil
}
// If multi factor authentication is enabled and is email based login and email otp is enabled // If multi factor authentication is enabled and is email based login and email otp is enabled
if refs.BoolValue(user.IsMultiFactorAuthEnabled) && !isMFADisabled && !isMailOTPDisabled && isEmailServiceEnabled && isEmailLogin { if refs.BoolValue(user.IsMultiFactorAuthEnabled) && !isMFADisabled && !isMailOTPDisabled && isEmailServiceEnabled && isEmailLogin {
expiresAt := time.Now().Add(1 * time.Minute).Unix() expiresAt := time.Now().Add(1 * time.Minute).Unix()
otpData, err := generateOTP(expiresAt) otpData, err := generateOTP(expiresAt)
go func() {
if err != nil { if err != nil {
log.Debug("Failed to generate otp: ", err) log.Debug("Failed to generate otp: ", err)
return return nil, err
} }
if err := setOTPMFaSession(expiresAt); err != nil { if err := setOTPMFaSession(expiresAt); err != nil {
log.Debug("Failed to set mfa session: ", err) log.Debug("Failed to set mfa session: ", err)
return return nil, err
} }
go func() {
// exec it as go routine so that we can reduce the api latency // exec it as go routine so that we can reduce the api latency
if err := mailService.SendEmail([]string{email}, constants.VerificationTypeOTP, map[string]interface{}{ if err := mailService.SendEmail([]string{email}, constants.VerificationTypeOTP, map[string]interface{}{
"user": user.ToMap(), "user": user.ToMap(),
@ -214,15 +271,15 @@ func LoginResolver(ctx context.Context, params model.LoginInput) (*model.AuthRes
if refs.BoolValue(user.IsMultiFactorAuthEnabled) && !isMFADisabled && !isSMSOTPDisabled && isSMSServiceEnabled && isMobileLogin { if refs.BoolValue(user.IsMultiFactorAuthEnabled) && !isMFADisabled && !isSMSOTPDisabled && isSMSServiceEnabled && isMobileLogin {
expiresAt := time.Now().Add(1 * time.Minute).Unix() expiresAt := time.Now().Add(1 * time.Minute).Unix()
otpData, err := generateOTP(expiresAt) otpData, err := generateOTP(expiresAt)
go func() {
if err != nil { if err != nil {
log.Debug("Failed to generate otp: ", err) log.Debug("Failed to generate otp: ", err)
return return nil, err
} }
if err := setOTPMFaSession(expiresAt); err != nil { if err := setOTPMFaSession(expiresAt); err != nil {
log.Debug("Failed to set mfa session: ", err) log.Debug("Failed to set mfa session: ", err)
return return nil, err
} }
go func() {
smsBody := strings.Builder{} smsBody := strings.Builder{}
smsBody.WriteString("Your verification code is: ") smsBody.WriteString("Your verification code is: ")
smsBody.WriteString(otpData.Otp) smsBody.WriteString(otpData.Otp)

View File

@ -7,12 +7,14 @@ import (
"strings" "strings"
"time" "time"
"github.com/google/uuid"
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/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/db/models"
emailHelper "github.com/authorizerdev/authorizer/server/email" mailService "github.com/authorizerdev/authorizer/server/email"
"github.com/authorizerdev/authorizer/server/graph/model" "github.com/authorizerdev/authorizer/server/graph/model"
"github.com/authorizerdev/authorizer/server/memorystore" "github.com/authorizerdev/authorizer/server/memorystore"
"github.com/authorizerdev/authorizer/server/refs" "github.com/authorizerdev/authorizer/server/refs"
@ -32,44 +34,42 @@ func ResendOTPResolver(ctx context.Context, params model.ResendOTPRequest) (*mod
log.Debug("Email or phone number is required") log.Debug("Email or phone number is required")
return nil, errors.New("email or phone number is required") return nil, errors.New("email or phone number is required")
} }
gc, err := utils.GinContextFromContext(ctx)
if err != nil {
log.Debug("Failed to get GinContext: ", err)
return nil, err
}
var user *models.User var user *models.User
var err error var isEmailServiceEnabled, isSMSServiceEnabled bool
if email != "" { if email != "" {
isEmailServiceEnabled, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyIsEmailServiceEnabled) isEmailServiceEnabled, err = memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyIsEmailServiceEnabled)
if err != nil || !isEmailServiceEnabled { if err != nil || !isEmailServiceEnabled {
log.Debug("Email service not enabled: ", err) log.Debug("Email service not enabled: ", err)
return nil, errors.New("email service not enabled") return nil, errors.New("email service not enabled")
} }
user, err = db.Provider.GetUserByEmail(ctx, email) user, err = db.Provider.GetUserByEmail(ctx, email)
if err != nil {
log.Debug("Failed to get user by email: ", err)
return nil, fmt.Errorf(`user with this email/phone not found`)
}
} else { } else {
isSMSServiceEnabled, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyIsEmailServiceEnabled) isSMSServiceEnabled, err = memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyIsEmailServiceEnabled)
if err != nil || !isSMSServiceEnabled { if err != nil || !isSMSServiceEnabled {
log.Debug("Email service not enabled: ", err) log.Debug("Email service not enabled: ", err)
return nil, errors.New("email service not enabled") return nil, errors.New("email service not enabled")
} }
user, err = db.Provider.GetUserByPhoneNumber(ctx, phoneNumber) user, err = db.Provider.GetUserByPhoneNumber(ctx, phoneNumber)
}
if err != nil { if err != nil {
log.Debug("Failed to get user by email: ", err) log.Debug("Failed to get user by phone: ", err)
return nil, fmt.Errorf(`user with this email/phone not found`) return nil, fmt.Errorf(`user with this email/phone not found`)
} }
}
if user.RevokedTimestamp != nil { if user.RevokedTimestamp != nil {
log.Debug("User access is revoked") log.Debug("User access is revoked")
return nil, fmt.Errorf(`user access has been revoked`) return nil, fmt.Errorf(`user access has been revoked`)
} }
if email != "" && user.EmailVerifiedAt == nil { if !refs.BoolValue(user.IsMultiFactorAuthEnabled) && user.EmailVerifiedAt != nil && user.PhoneNumberVerifiedAt != nil {
log.Debug("User email is not verified")
return nil, fmt.Errorf(`email not verified`)
}
if phoneNumber != "" && user.PhoneNumberVerifiedAt == nil {
log.Debug("User phone number is not verified")
return nil, fmt.Errorf(`phone number not verified`)
}
if !refs.BoolValue(user.IsMultiFactorAuthEnabled) {
log.Debug("User multi factor authentication is not enabled") log.Debug("User multi factor authentication is not enabled")
return nil, fmt.Errorf(`multi factor authentication not enabled`) return nil, fmt.Errorf(`multi factor authentication not enabled`)
} }
@ -97,30 +97,63 @@ func ResendOTPResolver(ctx context.Context, params model.ResendOTPRequest) (*mod
Message: "Failed to get for given email", Message: "Failed to get for given email",
}, errors.New("failed to get otp for given email") }, errors.New("failed to get otp for given email")
} }
// If multi factor authentication is enabled and we need to generate OTP for mail / sms based MFA
generateOTP := func(expiresAt int64) (*models.OTP, error) {
otp := utils.GenerateOTP() otp := utils.GenerateOTP()
if _, err := db.Provider.UpsertOTP(ctx, &models.OTP{ otpData, err := db.Provider.UpsertOTP(ctx, &models.OTP{
Email: refs.StringValue(user.Email), Email: refs.StringValue(user.Email),
PhoneNumber: refs.StringValue(user.PhoneNumber),
Otp: otp, Otp: otp,
ExpiresAt: time.Now().Add(1 * time.Minute).Unix(), ExpiresAt: expiresAt,
}); err != nil { })
log.Debug("Error upserting otp: ", err) if err != nil {
log.Debug("Failed to add otp: ", err)
return nil, err
}
return otpData, nil
}
setOTPMFaSession := func(expiresAt int64) error {
mfaSession := uuid.NewString()
err = memorystore.Provider.SetMfaSession(user.ID, mfaSession, expiresAt)
if err != nil {
log.Debug("Failed to add mfasession: ", err)
return err
}
cookie.SetMfaSession(gc, mfaSession)
return nil
}
expiresAt := time.Now().Add(1 * time.Minute).Unix()
otpData, err = generateOTP(expiresAt)
if err != nil {
log.Debug("Failed to generate otp: ", err)
return nil, err
}
if err := setOTPMFaSession(expiresAt); err != nil {
log.Debug("Failed to set mfa session: ", err)
return nil, err return nil, err
} }
if email != "" { if email != "" {
go func() {
// exec it as go routine so that we can reduce the api latency // exec it as go routine so that we can reduce the api latency
go emailHelper.SendEmail([]string{email}, constants.VerificationTypeOTP, map[string]interface{}{ if err := mailService.SendEmail([]string{email}, constants.VerificationTypeOTP, map[string]interface{}{
"user": user.ToMap(), "user": user.ToMap(),
"organization": utils.GetOrganization(), "organization": utils.GetOrganization(),
"otp": otp, "otp": otpData.Otp,
}) }); err != nil {
log.Debug("Failed to send otp email: ", err)
}
utils.RegisterEvent(ctx, constants.UserLoginWebhookEvent, constants.AuthRecipeMethodBasicAuth, user)
}()
} else { } else {
go func() {
smsBody := strings.Builder{} smsBody := strings.Builder{}
smsBody.WriteString("Your verification code is: ") smsBody.WriteString("Your verification code is: ")
smsBody.WriteString(otp) smsBody.WriteString(otpData.Otp)
// exec it as go routine so that we can reduce the api latency utils.RegisterEvent(ctx, constants.UserLoginWebhookEvent, constants.AuthRecipeMethodMobileBasicAuth, user)
go smsproviders.SendSMS(phoneNumber, smsBody.String()) if err := smsproviders.SendSMS(phoneNumber, smsBody.String()); err != nil {
log.Debug("Failed to send sms: ", err)
}
}()
} }
log.Info("OTP has been resent") log.Info("OTP has been resent")
return &model.Response{ return &model.Response{

View File

@ -290,25 +290,26 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR
} else if !disablePhoneVerification && isSMSServiceEnabled && isMobileSignup { } else if !disablePhoneVerification && isSMSServiceEnabled && isMobileSignup {
duration, _ := time.ParseDuration("10m") duration, _ := time.ParseDuration("10m")
smsCode := utils.GenerateOTP() smsCode := utils.GenerateOTP()
smsBody := strings.Builder{} smsBody := strings.Builder{}
smsBody.WriteString("Your verification code is: ") smsBody.WriteString("Your verification code is: ")
smsBody.WriteString(smsCode) smsBody.WriteString(smsCode)
expiresAt := time.Now().Add(duration).Unix()
// TODO: For those who enabled the webhook to call their sms vendor separately - sending the otp to their api
if err != nil {
log.Debug("error while upserting user: ", err.Error())
return nil, err
}
_, err = db.Provider.UpsertOTP(ctx, &models.OTP{ _, err = db.Provider.UpsertOTP(ctx, &models.OTP{
PhoneNumber: phoneNumber, PhoneNumber: phoneNumber,
Otp: smsCode, Otp: smsCode,
ExpiresAt: time.Now().Add(duration).Unix(), ExpiresAt: expiresAt,
}) })
if err != nil { if err != nil {
log.Debug("error while upserting OTP: ", err.Error()) log.Debug("error while upserting OTP: ", err.Error())
return nil, err return nil, err
} }
mfaSession := uuid.NewString()
err = memorystore.Provider.SetMfaSession(user.ID, mfaSession, expiresAt)
if err != nil {
log.Debug("Failed to add mfasession: ", err)
return nil, err
}
cookie.SetMfaSession(gc, mfaSession)
go func() { go func() {
smsproviders.SendSMS(phoneNumber, smsBody.String()) smsproviders.SendSMS(phoneNumber, smsBody.String())
utils.RegisterEvent(ctx, constants.UserCreatedWebhookEvent, constants.AuthRecipeMethodMobileBasicAuth, user) utils.RegisterEvent(ctx, constants.UserCreatedWebhookEvent, constants.AuthRecipeMethodMobileBasicAuth, user)

View File

@ -48,7 +48,18 @@ func UpdateUserResolver(ctx context.Context, params model.UpdateUserInput) (*mod
"user_id": params.ID, "user_id": params.ID,
}) })
if params.GivenName == nil && params.FamilyName == nil && params.Picture == nil && params.MiddleName == nil && params.Nickname == nil && params.Email == nil && params.Birthdate == nil && params.Gender == nil && params.PhoneNumber == nil && params.Roles == nil && params.IsMultiFactorAuthEnabled == nil && params.AppData == nil { if params.GivenName == nil &&
params.FamilyName == nil &&
params.Picture == nil &&
params.MiddleName == nil &&
params.Nickname == nil &&
params.Email == nil &&
params.Birthdate == nil &&
params.Gender == nil &&
params.PhoneNumber == nil &&
params.Roles == nil &&
params.IsMultiFactorAuthEnabled == nil &&
params.AppData == nil {
log.Debug("No params to update") log.Debug("No params to update")
return res, fmt.Errorf("please enter atleast one param to update") return res, fmt.Errorf("please enter atleast one param to update")
} }
@ -142,6 +153,15 @@ func UpdateUserResolver(ctx context.Context, params model.UpdateUserInput) (*mod
user.EmailVerifiedAt = nil user.EmailVerifiedAt = nil
} }
} }
if params.PhoneNumberVerified != nil {
if *params.PhoneNumberVerified {
now := time.Now().Unix()
user.PhoneNumberVerifiedAt = &now
} else {
user.PhoneNumberVerifiedAt = nil
}
}
if params.Email != nil && refs.StringValue(user.Email) != refs.StringValue(params.Email) { if params.Email != nil && refs.StringValue(user.Email) != refs.StringValue(params.Email) {
// check if valid email // check if valid email
@ -197,6 +217,24 @@ func UpdateUserResolver(ctx context.Context, params model.UpdateUserInput) (*mod
} }
if params.PhoneNumber != nil && refs.StringValue(user.PhoneNumber) != refs.StringValue(params.PhoneNumber) {
phone := strings.TrimSpace(refs.StringValue(params.PhoneNumber))
if len(phone) < 10 || len(phone) > 15 {
log.Debug("Invalid phone number: ", *params.PhoneNumber)
return res, fmt.Errorf("invalid phone number")
}
// check if user with new phone number exists
_, err = db.Provider.GetUserByPhoneNumber(ctx, phone)
// err = nil means user exists
if err == nil {
log.Debug("User with phone number already exists: ", phone)
return res, fmt.Errorf("user with this phone number already exists")
}
go memorystore.Provider.DeleteAllUserSessions(user.ID)
user.PhoneNumber = &phone
user.PhoneNumberVerifiedAt = nil
}
rolesToSave := "" rolesToSave := ""
if params.Roles != nil && len(params.Roles) > 0 { if params.Roles != nil && len(params.Roles) > 0 {
currentRoles := strings.Split(user.Roles, ",") currentRoles := strings.Split(user.Roles, ",")
@ -237,7 +275,6 @@ func UpdateUserResolver(ctx context.Context, params model.UpdateUserInput) (*mod
if rolesToSave != "" { if rolesToSave != "" {
user.Roles = rolesToSave user.Roles = rolesToSave
} }
user, err = db.Provider.UpdateUser(ctx, user) user, err = db.Provider.UpdateUser(ctx, user)
if err != nil { if err != nil {
log.Debug("Failed to update user: ", err) log.Debug("Failed to update user: ", err)

View File

@ -16,6 +16,7 @@ func InitRouter(log *logrus.Logger) *gin.Engine {
router.Use(middlewares.Logger(log), gin.Recovery()) router.Use(middlewares.Logger(log), gin.Recovery())
router.Use(middlewares.GinContextToContextMiddleware()) router.Use(middlewares.GinContextToContextMiddleware())
router.Use(middlewares.CORSMiddleware()) router.Use(middlewares.CORSMiddleware())
router.Use(middlewares.ClientCheckMiddleware())
router.GET("/", handlers.RootHandler()) router.GET("/", handlers.RootHandler())
router.GET("/health", handlers.HealthHandler()) router.GET("/health", handlers.HealthHandler())

View File

@ -28,9 +28,11 @@ func loginTests(t *testing.T, s TestSetup) {
Email: refs.NewStringRef(email), Email: refs.NewStringRef(email),
Password: s.TestInfo.Password, Password: s.TestInfo.Password,
}) })
// access token should be empty as email is not verified
assert.NotNil(t, err, "should fail because email is not verified") assert.NoError(t, err)
assert.Nil(t, res) assert.NotNil(t, res)
assert.Nil(t, res.AccessToken)
assert.NotEmpty(t, res.Message)
verificationRequest, err := db.Provider.GetVerificationRequestByEmail(ctx, email, constants.VerificationTypeBasicAuthSignup) verificationRequest, err := db.Provider.GetVerificationRequestByEmail(ctx, email, constants.VerificationTypeBasicAuthSignup)
assert.NoError(t, err) assert.NoError(t, err)
assert.NotNil(t, verificationRequest) assert.NotNil(t, verificationRequest)

View File

@ -33,8 +33,12 @@ func mobileLoginTests(t *testing.T, s TestSetup) {
PhoneNumber: refs.NewStringRef(phoneNumber), PhoneNumber: refs.NewStringRef(phoneNumber),
Password: s.TestInfo.Password, Password: s.TestInfo.Password,
}) })
assert.NotNil(t, err, "should fail because phone is not verified") // access token should be empty as email is not verified
assert.Nil(t, res) assert.NoError(t, err)
assert.NotNil(t, res)
assert.Nil(t, res.AccessToken)
assert.NotEmpty(t, res.Message)
assert.True(t, *res.ShouldShowMobileOtpScreen)
smsRequest, err := db.Provider.GetOTPByPhoneNumber(ctx, phoneNumber) smsRequest, err := db.Provider.GetOTPByPhoneNumber(ctx, phoneNumber)
assert.NoError(t, err) assert.NoError(t, err)
assert.NotEmpty(t, smsRequest.Otp) assert.NotEmpty(t, smsRequest.Otp)

View File

@ -35,8 +35,11 @@ func resendOTPTest(t *testing.T, s TestSetup) {
Email: refs.NewStringRef(email), Email: refs.NewStringRef(email),
Password: s.TestInfo.Password, Password: s.TestInfo.Password,
}) })
assert.Error(t, err) // access token should be empty as email is not verified
assert.Nil(t, loginRes) assert.NoError(t, err)
assert.NotNil(t, loginRes)
assert.Nil(t, loginRes.AccessToken)
assert.NotEmpty(t, loginRes.Message)
verificationRequest, err := db.Provider.GetVerificationRequestByEmail(ctx, email, constants.VerificationTypeBasicAuthSignup) verificationRequest, err := db.Provider.GetVerificationRequestByEmail(ctx, email, constants.VerificationTypeBasicAuthSignup)
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, email, verificationRequest.Email) assert.Equal(t, email, verificationRequest.Email)
@ -57,13 +60,6 @@ func resendOTPTest(t *testing.T, s TestSetup) {
memorystore.Provider.UpdateEnvVariable(constants.EnvKeyDisableMailOTPLogin, false) memorystore.Provider.UpdateEnvVariable(constants.EnvKeyDisableMailOTPLogin, false)
memorystore.Provider.UpdateEnvVariable(constants.EnvKeyDisableTOTPLogin, true) memorystore.Provider.UpdateEnvVariable(constants.EnvKeyDisableTOTPLogin, true)
// Resend otp should return error as no initial opt is being sent
resendOtpRes, err := resolvers.ResendOTPResolver(ctx, model.ResendOTPRequest{
Email: refs.NewStringRef(email),
})
assert.Error(t, err)
assert.Nil(t, resendOtpRes)
// Login should not return error but access token should be empty as otp should have been sent // Login should not return error but access token should be empty as otp should have been sent
loginRes, err = resolvers.LoginResolver(ctx, model.LoginInput{ loginRes, err = resolvers.LoginResolver(ctx, model.LoginInput{
Email: refs.NewStringRef(email), Email: refs.NewStringRef(email),
@ -79,7 +75,7 @@ func resendOTPTest(t *testing.T, s TestSetup) {
assert.NotEmpty(t, otp.Otp) assert.NotEmpty(t, otp.Otp)
// resend otp // resend otp
resendOtpRes, err = resolvers.ResendOTPResolver(ctx, model.ResendOTPRequest{ resendOtpRes, err := resolvers.ResendOTPResolver(ctx, model.ResendOTPRequest{
Email: refs.NewStringRef(email), Email: refs.NewStringRef(email),
}) })
assert.NoError(t, err) assert.NoError(t, err)

View File

@ -42,8 +42,11 @@ func totpLoginTest(t *testing.T, s TestSetup) {
Email: &email, Email: &email,
Password: s.TestInfo.Password, Password: s.TestInfo.Password,
}) })
assert.Error(t, err) // access token should be empty as email is not verified
assert.Nil(t, loginRes) assert.NoError(t, err)
assert.NotNil(t, loginRes)
assert.Nil(t, loginRes.AccessToken)
assert.NotEmpty(t, loginRes.Message)
verificationRequest, err := db.Provider.GetVerificationRequestByEmail(ctx, email, constants.VerificationTypeBasicAuthSignup) verificationRequest, err := db.Provider.GetVerificationRequestByEmail(ctx, email, constants.VerificationTypeBasicAuthSignup)
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, email, verificationRequest.Email) assert.Equal(t, email, verificationRequest.Email)

View File

@ -47,8 +47,10 @@ func verifyOTPTest(t *testing.T, s TestSetup) {
Email: refs.NewStringRef(email), Email: refs.NewStringRef(email),
Password: s.TestInfo.Password, Password: s.TestInfo.Password,
}) })
assert.NotNil(t, err, "email is not verified") assert.NoError(t, err)
assert.Nil(t, loginRes) assert.NotNil(t, loginRes)
assert.Nil(t, loginRes.AccessToken)
assert.NotEmpty(t, loginRes.Message)
// Verify the email // Verify the email
verificationRequest, err := db.Provider.GetVerificationRequestByEmail(ctx, email, constants.VerificationTypeBasicAuthSignup) verificationRequest, err := db.Provider.GetVerificationRequestByEmail(ctx, email, constants.VerificationTypeBasicAuthSignup)