Compare commits

...

17 Commits

Author SHA1 Message Date
Lakhan Samani
b7aeff57af fixes #160 2022-04-30 12:45:08 +05:30
Lakhan Samani
075c287f34 feat: add support for database cert, key, ca-cert 2022-04-23 17:52:02 +05:30
Lakhan Samani
4778827545 Merge pull request #144 from authorizerdev/feat/casandra-db
feat: add support for cassandra db
2022-04-22 21:26:10 +05:30
Lakhan Samani
39c2c364d9 feat: add support for db username, password, host, port 2022-04-22 21:24:39 +05:30
Lakhan Samani
961f2271c1 fix: tests 2022-04-22 19:56:55 +05:30
Lakhan Samani
aaf0831793 feat: add users queries 2022-04-22 16:45:49 +05:30
Lakhan Samani
27cb41c54c feat: add verification_request queries 2022-04-22 11:52:15 +05:30
Lakhan Samani
718b2d535f feat: add session queries 2022-04-21 18:11:15 +05:30
Lakhan Samani
ed6a1ceccc feat: add env queries 2022-04-21 17:54:33 +05:30
Lakhan Samani
fd52d6e5d3 feat: add casandradb provider 2022-04-21 12:36:22 +05:30
Lakhan Samani
325aa88368 Merge branch 'main' of https://github.com/authorizerdev/authorizer into feat/casandra-db 2022-04-20 23:32:02 +05:30
Lakhan Samani
75e44ff698 fix: cors error for x-authorizer-url 2022-04-10 14:43:19 +05:30
Lakhan Samani
d5f1c5a5eb Resolves #156 2022-04-02 17:34:50 +05:30
Lakhan Samani
39947f1753 Merge pull request #155 from authorizerdev/fix/gateway-based-setup
fix: setting the cookie for proxy setup
2022-03-30 11:51:20 +05:30
Lakhan Samani
4fa9f79c3f fix: setting the cookie for proxy setup 2022-03-30 11:50:22 +05:30
Lakhan Samani
fe73c2f6f8 Update README.md 2022-03-26 07:00:01 +05:30
Lakhan Samani
a6b743465f feat: add provider template 2022-03-19 17:41:27 +05:30
48 changed files with 1208 additions and 125 deletions

View File

@@ -9,3 +9,4 @@ build
data.db data.db
app/node_modules app/node_modules
app/build app/build
certs/

3
.gitignore vendored
View File

@@ -13,4 +13,5 @@ data.db
*.tar.gz *.tar.gz
.vscode/ .vscode/
.yalc .yalc
yalc.lock yalc.lock
certs/

View File

@@ -26,18 +26,16 @@
- ✅ Sign-in / Sign-up with email ID and password - ✅ Sign-in / Sign-up with email ID and password
- ✅ Secure session management - ✅ Secure session management
- ✅ Email verification - ✅ Email verification
- ✅ OAuth2 and OpenID compatible APIs
- ✅ APIs to update profile securely - ✅ APIs to update profile securely
- ✅ Forgot password flow using email - ✅ Forgot password flow using email
- ✅ Social logins (Google, Github, Facebook, more coming soon) - ✅ Social logins (Google, Github, Facebook, more coming soon)
- ✅ Role-based access management - ✅ Role-based access management
- ✅ Password-less login with email and magic link - ✅ Password-less login with magic link login
## Roadmap ## Roadmap
- Support more JWT encryption algorithms (Currently supporting HS256)
- 2 Factor authentication - 2 Factor authentication
- Back office (Admin dashboard to manage user)
- Support more database
- VueJS SDK - VueJS SDK
- Svelte SDK - Svelte SDK
- React Native SDK - React Native SDK

30
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": "latest", "@authorizerdev/authorizer-react": "^0.17.0",
"@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",
@@ -24,9 +24,9 @@
} }
}, },
"node_modules/@authorizerdev/authorizer-js": { "node_modules/@authorizerdev/authorizer-js": {
"version": "0.6.0", "version": "0.10.0",
"resolved": "https://registry.npmjs.org/@authorizerdev/authorizer-js/-/authorizer-js-0.6.0.tgz", "resolved": "https://registry.npmjs.org/@authorizerdev/authorizer-js/-/authorizer-js-0.10.0.tgz",
"integrity": "sha512-WbqeUmhQwLNlvk4ZYTptlbAIINh7aZPyTCVA/B0FE3EoPtx1tNOtkPtJOycrn0H0HyueeXQnBSCDxkvPAP65Bw==", "integrity": "sha512-REM8FLD/Ej9gzA2zDGDAke6QFss33ubePlTDmLDmIYUuQmpHFlO5mCCS6nVsKkN7F/Bcwkmp+eUNQjkdGCaKLg==",
"dependencies": { "dependencies": {
"node-fetch": "^2.6.1" "node-fetch": "^2.6.1"
}, },
@@ -35,11 +35,11 @@
} }
}, },
"node_modules/@authorizerdev/authorizer-react": { "node_modules/@authorizerdev/authorizer-react": {
"version": "0.11.0", "version": "0.17.0",
"resolved": "https://registry.npmjs.org/@authorizerdev/authorizer-react/-/authorizer-react-0.11.0.tgz", "resolved": "https://registry.npmjs.org/@authorizerdev/authorizer-react/-/authorizer-react-0.17.0.tgz",
"integrity": "sha512-VzSZvEB/t6N2ESn4O8c/+2hPUO7L4Iux8IBzXKrobKkoqRyb+u5TPZn0UWCOaoxIdiiZY+1Yq2A/H6q9LAqLGw==", "integrity": "sha512-7WcNCU7hDFkVfFb8LcJXFwWiLYd8aY78z1AbNPxCa2Cw5G85PaRkzjKybP6h01ITVOHO6M03lLwPj8p6Sr6fEg==",
"dependencies": { "dependencies": {
"@authorizerdev/authorizer-js": "^0.6.0", "@authorizerdev/authorizer-js": "^0.10.0",
"final-form": "^4.20.2", "final-form": "^4.20.2",
"react-final-form": "^6.5.3", "react-final-form": "^6.5.3",
"styled-components": "^5.3.0" "styled-components": "^5.3.0"
@@ -829,19 +829,19 @@
}, },
"dependencies": { "dependencies": {
"@authorizerdev/authorizer-js": { "@authorizerdev/authorizer-js": {
"version": "0.6.0", "version": "0.10.0",
"resolved": "https://registry.npmjs.org/@authorizerdev/authorizer-js/-/authorizer-js-0.6.0.tgz", "resolved": "https://registry.npmjs.org/@authorizerdev/authorizer-js/-/authorizer-js-0.10.0.tgz",
"integrity": "sha512-WbqeUmhQwLNlvk4ZYTptlbAIINh7aZPyTCVA/B0FE3EoPtx1tNOtkPtJOycrn0H0HyueeXQnBSCDxkvPAP65Bw==", "integrity": "sha512-REM8FLD/Ej9gzA2zDGDAke6QFss33ubePlTDmLDmIYUuQmpHFlO5mCCS6nVsKkN7F/Bcwkmp+eUNQjkdGCaKLg==",
"requires": { "requires": {
"node-fetch": "^2.6.1" "node-fetch": "^2.6.1"
} }
}, },
"@authorizerdev/authorizer-react": { "@authorizerdev/authorizer-react": {
"version": "0.11.0", "version": "0.17.0",
"resolved": "https://registry.npmjs.org/@authorizerdev/authorizer-react/-/authorizer-react-0.11.0.tgz", "resolved": "https://registry.npmjs.org/@authorizerdev/authorizer-react/-/authorizer-react-0.17.0.tgz",
"integrity": "sha512-VzSZvEB/t6N2ESn4O8c/+2hPUO7L4Iux8IBzXKrobKkoqRyb+u5TPZn0UWCOaoxIdiiZY+1Yq2A/H6q9LAqLGw==", "integrity": "sha512-7WcNCU7hDFkVfFb8LcJXFwWiLYd8aY78z1AbNPxCa2Cw5G85PaRkzjKybP6h01ITVOHO6M03lLwPj8p6Sr6fEg==",
"requires": { "requires": {
"@authorizerdev/authorizer-js": "^0.6.0", "@authorizerdev/authorizer-js": "^0.10.0",
"final-form": "^4.20.2", "final-form": "^4.20.2",
"react-final-form": "^6.5.3", "react-final-form": "^6.5.3",
"styled-components": "^5.3.0" "styled-components": "^5.3.0"

View File

@@ -11,7 +11,7 @@
"author": "Lakhan Samani", "author": "Lakhan Samani",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@authorizerdev/authorizer-react": "latest", "@authorizerdev/authorizer-react": "^0.17.0",
"@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

@@ -10,6 +10,9 @@ const queryClient = createClient({
fetchOptions: () => { fetchOptions: () => {
return { return {
credentials: 'include', credentials: 'include',
headers: {
'x-authorizer-url': window.location.origin,
},
}; };
}, },
requestPolicy: 'network-only', requestPolicy: 'network-only',

View File

@@ -17,4 +17,6 @@ const (
DbTypeYugabyte = "yugabyte" DbTypeYugabyte = "yugabyte"
// DbTypeMariaDB is the mariadb database type // DbTypeMariaDB is the mariadb database type
DbTypeMariaDB = "mariadb" DbTypeMariaDB = "mariadb"
// DbTypeCassandra is the cassandra database type
DbTypeCassandraDB = "cassandradb"
) )

View File

@@ -16,7 +16,6 @@ const (
// EnvKeyEnvPath key for cli arg variable ENV_PATH // EnvKeyEnvPath key for cli arg variable ENV_PATH
EnvKeyEnvPath = "ENV_PATH" EnvKeyEnvPath = "ENV_PATH"
// EnvKeyAuthorizerURL key for env variable AUTHORIZER_URL // EnvKeyAuthorizerURL key for env variable AUTHORIZER_URL
// TODO: remove support AUTHORIZER_URL env
EnvKeyAuthorizerURL = "AUTHORIZER_URL" EnvKeyAuthorizerURL = "AUTHORIZER_URL"
// EnvKeyPort key for env variable PORT // EnvKeyPort key for env variable PORT
EnvKeyPort = "PORT" EnvKeyPort = "PORT"
@@ -31,6 +30,20 @@ const (
EnvKeyDatabaseURL = "DATABASE_URL" EnvKeyDatabaseURL = "DATABASE_URL"
// EnvKeyDatabaseName key for env variable DATABASE_NAME // EnvKeyDatabaseName key for env variable DATABASE_NAME
EnvKeyDatabaseName = "DATABASE_NAME" EnvKeyDatabaseName = "DATABASE_NAME"
// EnvKeyDatabaseUsername key for env variable DATABASE_USERNAME
EnvKeyDatabaseUsername = "DATABASE_USERNAME"
// EnvKeyDatabasePassword key for env variable DATABASE_PASSWORD
EnvKeyDatabasePassword = "DATABASE_PASSWORD"
// EnvKeyDatabasePort key for env variable DATABASE_PORT
EnvKeyDatabasePort = "DATABASE_PORT"
// EnvKeyDatabaseHost key for env variable DATABASE_HOST
EnvKeyDatabaseHost = "DATABASE_HOST"
// EnvKeyDatabaseCert key for env variable DATABASE_CERT
EnvKeyDatabaseCert = "DATABASE_CERT"
// EnvKeyDatabaseCertKey key for env variable DATABASE_KEY
EnvKeyDatabaseCertKey = "DATABASE_CERT_KEY"
// EnvKeyDatabaseCACert key for env variable DATABASE_CA_CERT
EnvKeyDatabaseCACert = "DATABASE_CA_CERT"
// EnvKeySmtpHost key for env variable SMTP_HOST // EnvKeySmtpHost key for env variable SMTP_HOST
EnvKeySmtpHost = "SMTP_HOST" EnvKeySmtpHost = "SMTP_HOST"
// EnvKeySmtpPort key for env variable SMTP_PORT // EnvKeySmtpPort key for env variable SMTP_PORT

View File

@@ -4,6 +4,7 @@ import (
"github.com/authorizerdev/authorizer/server/constants" "github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/db/providers" "github.com/authorizerdev/authorizer/server/db/providers"
"github.com/authorizerdev/authorizer/server/db/providers/arangodb" "github.com/authorizerdev/authorizer/server/db/providers/arangodb"
"github.com/authorizerdev/authorizer/server/db/providers/cassandradb"
"github.com/authorizerdev/authorizer/server/db/providers/mongodb" "github.com/authorizerdev/authorizer/server/db/providers/mongodb"
"github.com/authorizerdev/authorizer/server/db/providers/sql" "github.com/authorizerdev/authorizer/server/db/providers/sql"
"github.com/authorizerdev/authorizer/server/envstore" "github.com/authorizerdev/authorizer/server/envstore"
@@ -15,9 +16,10 @@ var Provider providers.Provider
func InitDB() error { func InitDB() error {
var err error var err error
isSQL := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType) != constants.DbTypeArangodb && envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType) != constants.DbTypeMongodb isSQL := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType) != constants.DbTypeArangodb && envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType) != constants.DbTypeMongodb && envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType) != constants.DbTypeCassandraDB
isArangoDB := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType) == constants.DbTypeArangodb isArangoDB := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType) == constants.DbTypeArangodb
isMongoDB := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType) == constants.DbTypeMongodb isMongoDB := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType) == constants.DbTypeMongodb
isCassandra := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType) == constants.DbTypeCassandraDB
if isSQL { if isSQL {
Provider, err = sql.NewProvider() Provider, err = sql.NewProvider()
@@ -40,5 +42,12 @@ func InitDB() error {
} }
} }
if isCassandra {
Provider, err = cassandradb.NewProvider()
if err != nil {
return err
}
}
return nil return nil
} }

View File

@@ -1,11 +1,13 @@
package models package models
// Note: any change here should be reflected in providers/casandra/provider.go as it does not have model support in collection creation
// Env model for db // Env model for db
type Env struct { type Env struct {
Key string `json:"_key,omitempty" bson:"_key"` // for arangodb Key string `json:"_key,omitempty" bson:"_key,omitempty" cql:"_key,omitempty"` // for arangodb
ID string `gorm:"primaryKey;type:char(36)" json:"_id" bson:"_id"` ID string `gorm:"primaryKey;type:char(36)" json:"_id" bson:"_id" cql:"id"`
EnvData string `gorm:"type:text" json:"env" bson:"env"` EnvData string `gorm:"type:text" json:"env" bson:"env" cql:"env"`
Hash string `gorm:"type:text" json:"hash" bson:"hash"` Hash string `gorm:"type:text" json:"hash" bson:"hash" cql:"hash"`
UpdatedAt int64 `json:"updated_at" bson:"updated_at"` UpdatedAt int64 `json:"updated_at" bson:"updated_at" cql:"updated_at"`
CreatedAt int64 `json:"created_at" bson:"created_at"` CreatedAt int64 `json:"created_at" bson:"created_at" cql:"created_at"`
} }

View File

@@ -1,13 +1,15 @@
package models package models
// Note: any change here should be reflected in providers/casandra/provider.go as it does not have model support in collection creation
// Session model for db // Session model for db
type Session struct { type Session struct {
Key string `json:"_key,omitempty" bson:"_key,omitempty"` // for arangodb Key string `json:"_key,omitempty" bson:"_key,omitempty" cql:"_key,omitempty"` // for arangodb
ID string `gorm:"primaryKey;type:char(36)" json:"_id" bson:"_id"` ID string `gorm:"primaryKey;type:char(36)" json:"_id" bson:"_id" cql:"id"`
UserID string `gorm:"type:char(36),index:" json:"user_id" bson:"user_id"` UserID string `gorm:"type:char(36),index:" json:"user_id" bson:"user_id" cql:"user_id"`
User User `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"-" bson:"-"` User User `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"-" bson:"-" cql:"-"`
UserAgent string `json:"user_agent" bson:"user_agent"` UserAgent string `json:"user_agent" bson:"user_agent" cql:"user_agent"`
IP string `json:"ip" bson:"ip"` IP string `json:"ip" bson:"ip" cql:"ip"`
CreatedAt int64 `json:"created_at" bson:"created_at"` CreatedAt int64 `json:"created_at" bson:"created_at" cql:"created_at"`
UpdatedAt int64 `json:"updated_at" bson:"updated_at"` UpdatedAt int64 `json:"updated_at" bson:"updated_at" cql:"updated_at"`
} }

View File

@@ -6,28 +6,30 @@ import (
"github.com/authorizerdev/authorizer/server/graph/model" "github.com/authorizerdev/authorizer/server/graph/model"
) )
// Note: any change here should be reflected in providers/casandra/provider.go as it does not have model support in collection creation
// User model for db // User model for db
type User struct { type User struct {
Key string `json:"_key,omitempty" bson:"_key"` // for arangodb Key string `json:"_key,omitempty" bson:"_key,omitempty" cql:"_key,omitempty"` // for arangodb
ID string `gorm:"primaryKey;type:char(36)" json:"_id" bson:"_id"` ID string `gorm:"primaryKey;type:char(36)" json:"_id" bson:"_id" cql:"id"`
Email string `gorm:"unique" json:"email" bson:"email"` Email string `gorm:"unique" json:"email" bson:"email" cql:"email"`
EmailVerifiedAt *int64 `json:"email_verified_at" bson:"email_verified_at"` EmailVerifiedAt *int64 `json:"email_verified_at" bson:"email_verified_at" cql:"email_verified_at"`
Password *string `gorm:"type:text" json:"password" bson:"password"` Password *string `gorm:"type:text" json:"password" bson:"password" cql:"password"`
SignupMethods string `json:"signup_methods" bson:"signup_methods"` SignupMethods string `json:"signup_methods" bson:"signup_methods" cql:"signup_methods"`
GivenName *string `json:"given_name" bson:"given_name"` GivenName *string `json:"given_name" bson:"given_name" cql:"given_name"`
FamilyName *string `json:"family_name" bson:"family_name"` FamilyName *string `json:"family_name" bson:"family_name" cql:"family_name"`
MiddleName *string `json:"middle_name" bson:"middle_name"` MiddleName *string `json:"middle_name" bson:"middle_name" cql:"middle_name"`
Nickname *string `json:"nickname" bson:"nickname"` Nickname *string `json:"nickname" bson:"nickname" cql:"nickname"`
Gender *string `json:"gender" bson:"gender"` Gender *string `json:"gender" bson:"gender" cql:"gender"`
Birthdate *string `json:"birthdate" bson:"birthdate"` Birthdate *string `json:"birthdate" bson:"birthdate" cql:"birthdate"`
PhoneNumber *string `gorm:"unique" json:"phone_number" bson:"phone_number"` PhoneNumber *string `gorm:"unique" json:"phone_number" bson:"phone_number" cql:"phone_number"`
PhoneNumberVerifiedAt *int64 `json:"phone_number_verified_at" bson:"phone_number_verified_at"` PhoneNumberVerifiedAt *int64 `json:"phone_number_verified_at" bson:"phone_number_verified_at" cql:"phone_number_verified_at"`
Picture *string `gorm:"type:text" json:"picture" bson:"picture"` Picture *string `gorm:"type:text" json:"picture" bson:"picture" cql:"picture"`
Roles string `json:"roles" bson:"roles"` Roles string `json:"roles" bson:"roles" cql:"roles"`
UpdatedAt int64 `json:"updated_at" bson:"updated_at"` RevokedTimestamp *int64 `json:"revoked_timestamp" bson:"revoked_timestamp" cql:"revoked_timestamp"`
CreatedAt int64 `json:"created_at" bson:"created_at"` UpdatedAt int64 `json:"updated_at" bson:"updated_at" cql:"updated_at"`
RevokedTimestamp *int64 `json:"revoked_timestamp" bson:"revoked_timestamp"` CreatedAt int64 `json:"created_at" bson:"created_at" cql:"created_at"`
} }
func (user *User) AsAPIUser() *model.User { func (user *User) AsAPIUser() *model.User {
@@ -53,8 +55,8 @@ func (user *User) AsAPIUser() *model.User {
PhoneNumberVerified: &isPhoneVerified, PhoneNumberVerified: &isPhoneVerified,
Picture: user.Picture, Picture: user.Picture,
Roles: strings.Split(user.Roles, ","), Roles: strings.Split(user.Roles, ","),
RevokedTimestamp: revokedTimestamp,
CreatedAt: &createdAt, CreatedAt: &createdAt,
UpdatedAt: &updatedAt, UpdatedAt: &updatedAt,
RevokedTimestamp: revokedTimestamp,
} }
} }

View File

@@ -2,18 +2,20 @@ package models
import "github.com/authorizerdev/authorizer/server/graph/model" import "github.com/authorizerdev/authorizer/server/graph/model"
// Note: any change here should be reflected in providers/casandra/provider.go as it does not have model support in collection creation
// VerificationRequest model for db // VerificationRequest model for db
type VerificationRequest struct { type VerificationRequest struct {
Key string `json:"_key,omitempty" bson:"_key"` // for arangodb Key string `json:"_key,omitempty" bson:"_key" cql:"_key,omitempty"` // for arangodb
ID string `gorm:"primaryKey;type:char(36)" json:"_id" bson:"_id"` ID string `gorm:"primaryKey;type:char(36)" json:"_id" bson:"_id" cql:"id"`
Token string `gorm:"type:text" json:"token" bson:"token"` Token string `gorm:"type:text" json:"token" bson:"token" cql:"jwt_token"` // token is reserved keyword in cassandra
Identifier string `gorm:"uniqueIndex:idx_email_identifier" json:"identifier" bson:"identifier"` Identifier string `gorm:"uniqueIndex:idx_email_identifier;type:varchar(64)" json:"identifier" bson:"identifier" cql:"identifier"`
ExpiresAt int64 `json:"expires_at" bson:"expires_at"` ExpiresAt int64 `json:"expires_at" bson:"expires_at" cql:"expires_at"`
CreatedAt int64 `json:"created_at" bson:"created_at"` Email string `gorm:"uniqueIndex:idx_email_identifier;type:varchar(256)" json:"email" bson:"email" cql:"email"`
UpdatedAt int64 `json:"updated_at" bson:"updated_at"` Nonce string `gorm:"type:text" json:"nonce" bson:"nonce" cql:"nonce"`
Email string `gorm:"uniqueIndex:idx_email_identifier" json:"email" bson:"email"` RedirectURI string `gorm:"type:text" json:"redirect_uri" bson:"redirect_uri" cql:"redirect_uri"`
Nonce string `gorm:"type:text" json:"nonce" bson:"nonce"` CreatedAt int64 `json:"created_at" bson:"created_at" cql:"created_at"`
RedirectURI string `gorm:"type:text" json:"redirect_uri" bson:"redirect_uri"` UpdatedAt int64 `json:"updated_at" bson:"updated_at" cql:"updated_at"`
} }
func (v *VerificationRequest) AsAPIVerificationRequest() *model.VerificationRequest { func (v *VerificationRequest) AsAPIVerificationRequest() *model.VerificationRequest {
@@ -30,10 +32,10 @@ func (v *VerificationRequest) AsAPIVerificationRequest() *model.VerificationRequ
Token: &token, Token: &token,
Identifier: &identifier, Identifier: &identifier,
Expires: &expires, Expires: &expires,
CreatedAt: &createdAt,
UpdatedAt: &updatedAt,
Email: &email, Email: &email,
Nonce: &nonce, Nonce: &nonce,
RedirectURI: &redirectURI, RedirectURI: &redirectURI,
CreatedAt: &createdAt,
UpdatedAt: &updatedAt,
} }
} }

View File

@@ -0,0 +1,52 @@
package cassandradb
import (
"fmt"
"time"
"github.com/authorizerdev/authorizer/server/db/models"
"github.com/gocql/gocql"
"github.com/google/uuid"
)
// AddEnv to save environment information in database
func (p *provider) AddEnv(env models.Env) (models.Env, error) {
if env.ID == "" {
env.ID = uuid.New().String()
}
env.CreatedAt = time.Now().Unix()
env.UpdatedAt = time.Now().Unix()
insertEnvQuery := fmt.Sprintf("INSERT INTO %s (id, env, hash, created_at, updated_at) VALUES ('%s', '%s', '%s', %d, %d)", KeySpace+"."+models.Collections.Env, env.ID, env.EnvData, env.Hash, env.CreatedAt, env.UpdatedAt)
err := p.db.Query(insertEnvQuery).Exec()
if err != nil {
return env, err
}
return env, nil
}
// UpdateEnv to update environment information in database
func (p *provider) UpdateEnv(env models.Env) (models.Env, error) {
env.UpdatedAt = time.Now().Unix()
updateEnvQuery := fmt.Sprintf("UPDATE %s SET env = '%s', updated_at = %d WHERE id = '%s'", KeySpace+"."+models.Collections.Env, env.EnvData, env.UpdatedAt, env.ID)
err := p.db.Query(updateEnvQuery).Exec()
if err != nil {
return env, err
}
return env, nil
}
// GetEnv to get environment information from database
func (p *provider) GetEnv() (models.Env, error) {
var env models.Env
query := fmt.Sprintf("SELECT id, env, hash, created_at, updated_at FROM %s LIMIT 1", KeySpace+"."+models.Collections.Env)
err := p.db.Query(query).Consistency(gocql.One).Scan(&env.ID, &env.EnvData, &env.Hash, &env.CreatedAt, &env.UpdatedAt)
if err != nil {
return env, err
}
return env, nil
}

View File

@@ -0,0 +1,180 @@
package cassandradb
import (
"crypto/tls"
"crypto/x509"
"fmt"
"log"
"strings"
"github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/crypto"
"github.com/authorizerdev/authorizer/server/db/models"
"github.com/authorizerdev/authorizer/server/envstore"
"github.com/gocql/gocql"
cansandraDriver "github.com/gocql/gocql"
)
type provider struct {
db *cansandraDriver.Session
}
// KeySpace for the cassandra database
var KeySpace string
// NewProvider to initialize arangodb connection
func NewProvider() (*provider, error) {
dbURL := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseURL)
if dbURL == "" {
dbURL = envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseHost)
if envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabasePort) != "" {
dbURL = fmt.Sprintf("%s:%s", dbURL, envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabasePort))
}
}
KeySpace = envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseName)
clusterURL := []string{}
if strings.Contains(dbURL, ",") {
clusterURL = strings.Split(dbURL, ",")
} else {
clusterURL = append(clusterURL, dbURL)
}
cassandraClient := cansandraDriver.NewCluster(clusterURL...)
if envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseUsername) != "" && envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabasePassword) != "" {
cassandraClient.Authenticator = &cansandraDriver.PasswordAuthenticator{
Username: envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseUsername),
Password: envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabasePassword),
}
}
if envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseCert) != "" && envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseCACert) != "" && envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseCertKey) != "" {
certString, err := crypto.DecryptB64(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseCert))
if err != nil {
return nil, err
}
keyString, err := crypto.DecryptB64(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseCertKey))
if err != nil {
return nil, err
}
caString, err := crypto.DecryptB64(envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseCACert))
if err != nil {
return nil, err
}
cert, err := tls.X509KeyPair([]byte(certString), []byte(keyString))
if err != nil {
return nil, err
}
caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM([]byte(caString))
cassandraClient.SslOpts = &cansandraDriver.SslOptions{
Config: &tls.Config{
Certificates: []tls.Certificate{cert},
RootCAs: caCertPool,
InsecureSkipVerify: true,
},
EnableHostVerification: false,
}
}
cassandraClient.RetryPolicy = &cansandraDriver.SimpleRetryPolicy{
NumRetries: 3,
}
cassandraClient.Consistency = gocql.LocalQuorum
session, err := cassandraClient.CreateSession()
if err != nil {
log.Println("Error while creating connection to cassandra db", err)
return nil, err
}
// Note for astra keyspaces can only be created from there console
// https://docs.datastax.com/en/astra/docs/datastax-astra-faq.html#_i_am_trying_to_create_a_keyspace_in_the_cql_shell_and_i_am_running_into_an_error_how_do_i_fix_this
getKeyspaceQuery := fmt.Sprintf("SELECT keyspace_name FROM system_schema.keyspaces;")
scanner := session.Query(getKeyspaceQuery).Iter().Scanner()
hasAuthorizerKeySpace := false
for scanner.Next() {
var keySpace string
err := scanner.Scan(&keySpace)
if err != nil {
log.Println("Error while getting keyspace information", err)
return nil, err
}
if keySpace == KeySpace {
hasAuthorizerKeySpace = true
break
}
}
if !hasAuthorizerKeySpace {
createKeySpaceQuery := fmt.Sprintf("CREATE KEYSPACE %s WITH REPLICATION = {'class': 'SimpleStrategy', 'replication_factor': 1};", KeySpace)
err = session.Query(createKeySpaceQuery).Exec()
if err != nil {
log.Println("Error while creating keyspace", err)
return nil, err
}
}
// make sure collections are present
envCollectionQuery := fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s.%s (id text, env text, hash text, updated_at bigint, created_at bigint, PRIMARY KEY (id))",
KeySpace, models.Collections.Env)
err = session.Query(envCollectionQuery).Exec()
if err != nil {
log.Println("Unable to create env collection:", err)
return nil, err
}
sessionCollectionQuery := fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s.%s (id text, user_id text, user_agent text, ip text, updated_at bigint, created_at bigint, PRIMARY KEY (id))", KeySpace, models.Collections.Session)
err = session.Query(sessionCollectionQuery).Exec()
if err != nil {
log.Println("Unable to create session collection:", err)
return nil, err
}
userCollectionQuery := fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s.%s (id text, email text, email_verified_at bigint, password text, signup_methods text, given_name text, family_name text, middle_name text, nickname text, gender text, birthdate text, phone_number text, phone_number_verified_at bigint, picture text, roles text, updated_at bigint, created_at bigint, revoked_timestamp bigint, PRIMARY KEY (id))", KeySpace, models.Collections.User)
err = session.Query(userCollectionQuery).Exec()
if err != nil {
log.Println("Unable to create user collection:", err)
return nil, err
}
userIndexQuery := fmt.Sprintf("CREATE INDEX IF NOT EXISTS authorizer_user_email ON %s.%s (email)", KeySpace, models.Collections.User)
err = session.Query(userIndexQuery).Exec()
if err != nil {
log.Println("Unable to create user index:", err)
return nil, err
}
// token is reserved keyword in cassandra, hence we need to use jwt_token
verificationRequestCollectionQuery := fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s.%s (id text, jwt_token text, identifier text, expires_at bigint, email text, nonce text, redirect_uri text, created_at bigint, updated_at bigint, PRIMARY KEY (id))", KeySpace, models.Collections.VerificationRequest)
err = session.Query(verificationRequestCollectionQuery).Exec()
if err != nil {
log.Println("Unable to create verification request collection:", err)
return nil, err
}
verificationRequestIndexQuery := fmt.Sprintf("CREATE INDEX IF NOT EXISTS authorizer_verification_request_email ON %s.%s (email)", KeySpace, models.Collections.VerificationRequest)
err = session.Query(verificationRequestIndexQuery).Exec()
if err != nil {
log.Println("Unable to create verification_requests index:", err)
return nil, err
}
verificationRequestIndexQuery = fmt.Sprintf("CREATE INDEX IF NOT EXISTS authorizer_verification_request_identifier ON %s.%s (identifier)", KeySpace, models.Collections.VerificationRequest)
err = session.Query(verificationRequestIndexQuery).Exec()
if err != nil {
log.Println("Unable to create verification_requests index:", err)
return nil, err
}
verificationRequestIndexQuery = fmt.Sprintf("CREATE INDEX IF NOT EXISTS authorizer_verification_request_jwt_token ON %s.%s (jwt_token)", KeySpace, models.Collections.VerificationRequest)
err = session.Query(verificationRequestIndexQuery).Exec()
if err != nil {
log.Println("Unable to create verification_requests index:", err)
return nil, err
}
return &provider{
db: session,
}, err
}

View File

@@ -0,0 +1,36 @@
package cassandradb
import (
"fmt"
"time"
"github.com/authorizerdev/authorizer/server/db/models"
"github.com/google/uuid"
)
// AddSession to save session information in database
func (p *provider) AddSession(session models.Session) error {
if session.ID == "" {
session.ID = uuid.New().String()
}
session.CreatedAt = time.Now().Unix()
session.UpdatedAt = time.Now().Unix()
insertSessionQuery := fmt.Sprintf("INSERT INTO %s (id, user_id, user_agent, ip, created_at, updated_at) VALUES ('%s', '%s', '%s', '%s', %d, %d)", KeySpace+"."+models.Collections.Session, session.ID, session.UserID, session.UserAgent, session.IP, session.CreatedAt, session.UpdatedAt)
err := p.db.Query(insertSessionQuery).Exec()
if err != nil {
return err
}
return nil
}
// DeleteSession to delete session information from database
func (p *provider) DeleteSession(userId string) error {
deleteSessionQuery := fmt.Sprintf("DELETE FROM %s WHERE user_id = '%s'", KeySpace+"."+models.Collections.Session, userId)
err := p.db.Query(deleteSessionQuery).Exec()
if err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,189 @@
package cassandradb
import (
"encoding/json"
"fmt"
"reflect"
"strings"
"time"
"github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/db/models"
"github.com/authorizerdev/authorizer/server/envstore"
"github.com/authorizerdev/authorizer/server/graph/model"
"github.com/gocql/gocql"
"github.com/google/uuid"
)
// AddUser to save user information in database
func (p *provider) AddUser(user models.User) (models.User, error) {
if user.ID == "" {
user.ID = uuid.New().String()
}
if user.Roles == "" {
user.Roles = strings.Join(envstore.EnvStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyDefaultRoles), ",")
}
user.CreatedAt = time.Now().Unix()
user.UpdatedAt = time.Now().Unix()
bytes, err := json.Marshal(user)
if err != nil {
return user, err
}
// use decoder instead of json.Unmarshall, because it converts int64 -> float64 after unmarshalling
decoder := json.NewDecoder(strings.NewReader(string(bytes)))
decoder.UseNumber()
userMap := map[string]interface{}{}
err = decoder.Decode(&userMap)
if err != nil {
return user, err
}
fields := "("
values := "("
for key, value := range userMap {
if value != nil {
if key == "_id" {
fields += "id,"
} else {
fields += key + ","
}
valueType := reflect.TypeOf(value)
if valueType.Name() == "string" {
values += fmt.Sprintf("'%s',", value.(string))
} else {
values += fmt.Sprintf("%v,", value)
}
}
}
fields = fields[:len(fields)-1] + ")"
values = values[:len(values)-1] + ")"
query := fmt.Sprintf("INSERT INTO %s %s VALUES %s IF NOT EXISTS", KeySpace+"."+models.Collections.User, fields, values)
err = p.db.Query(query).Exec()
if err != nil {
return user, err
}
return user, nil
}
// UpdateUser to update user information in database
func (p *provider) UpdateUser(user models.User) (models.User, error) {
user.UpdatedAt = time.Now().Unix()
bytes, err := json.Marshal(user)
if err != nil {
return user, err
}
// use decoder instead of json.Unmarshall, because it converts int64 -> float64 after unmarshalling
decoder := json.NewDecoder(strings.NewReader(string(bytes)))
decoder.UseNumber()
userMap := map[string]interface{}{}
err = decoder.Decode(&userMap)
if err != nil {
return user, err
}
updateFields := ""
for key, value := range userMap {
if value != nil && key != "_id" {
}
if key == "_id" {
continue
}
if value == nil {
updateFields += fmt.Sprintf("%s = null,", key)
continue
}
valueType := reflect.TypeOf(value)
if valueType.Name() == "string" {
updateFields += fmt.Sprintf("%s = '%s', ", key, value.(string))
} else {
updateFields += fmt.Sprintf("%s = %v, ", key, value)
}
}
updateFields = strings.Trim(updateFields, " ")
updateFields = strings.TrimSuffix(updateFields, ",")
query := fmt.Sprintf("UPDATE %s SET %s WHERE id = '%s'", KeySpace+"."+models.Collections.User, updateFields, user.ID)
err = p.db.Query(query).Exec()
if err != nil {
return user, err
}
return user, nil
}
// DeleteUser to delete user information from database
func (p *provider) DeleteUser(user models.User) error {
query := fmt.Sprintf("DELETE FROM %s WHERE id = '%s'", KeySpace+"."+models.Collections.User, user.ID)
err := p.db.Query(query).Exec()
return err
}
// ListUsers to get list of users from database
func (p *provider) ListUsers(pagination model.Pagination) (*model.Users, error) {
responseUsers := []*model.User{}
paginationClone := pagination
totalCountQuery := fmt.Sprintf(`SELECT COUNT(*) FROM %s`, KeySpace+"."+models.Collections.User)
err := p.db.Query(totalCountQuery).Consistency(gocql.One).Scan(&paginationClone.Total)
if err != nil {
return nil, err
}
// there is no offset in cassandra
// so we fetch till limit + offset
// and return the results from offset to limit
query := fmt.Sprintf("SELECT id, email, email_verified_at, password, signup_methods, given_name, family_name, middle_name, nickname, birthdate, phone_number, phone_number_verified_at, picture, roles, revoked_timestamp, created_at, updated_at FROM %s LIMIT %d", KeySpace+"."+models.Collections.User, pagination.Limit+pagination.Offset)
scanner := p.db.Query(query).Iter().Scanner()
counter := int64(0)
for scanner.Next() {
if counter >= pagination.Offset {
var user models.User
err := scanner.Scan(&user.ID, &user.Email, &user.EmailVerifiedAt, &user.Password, &user.SignupMethods, &user.GivenName, &user.FamilyName, &user.MiddleName, &user.Nickname, &user.Birthdate, &user.PhoneNumber, &user.PhoneNumberVerifiedAt, &user.Picture, &user.Roles, &user.RevokedTimestamp, &user.CreatedAt, &user.UpdatedAt)
if err != nil {
return nil, err
}
responseUsers = append(responseUsers, user.AsAPIUser())
}
counter++
}
return &model.Users{
Users: responseUsers,
Pagination: &paginationClone,
}, nil
}
// GetUserByEmail to get user information from database using email address
func (p *provider) GetUserByEmail(email string) (models.User, error) {
var user models.User
query := fmt.Sprintf("SELECT id, email, email_verified_at, password, signup_methods, given_name, family_name, middle_name, nickname, birthdate, phone_number, phone_number_verified_at, picture, roles, revoked_timestamp, created_at, updated_at FROM %s WHERE email = '%s' LIMIT 1", KeySpace+"."+models.Collections.User, email)
err := p.db.Query(query).Consistency(gocql.One).Scan(&user.ID, &user.Email, &user.EmailVerifiedAt, &user.Password, &user.SignupMethods, &user.GivenName, &user.FamilyName, &user.MiddleName, &user.Nickname, &user.Birthdate, &user.PhoneNumber, &user.PhoneNumberVerifiedAt, &user.Picture, &user.Roles, &user.RevokedTimestamp, &user.CreatedAt, &user.UpdatedAt)
if err != nil {
return user, err
}
return user, nil
}
// GetUserByID to get user information from database using user ID
func (p *provider) GetUserByID(id string) (models.User, error) {
var user models.User
query := fmt.Sprintf("SELECT id, email, email_verified_at, password, signup_methods, given_name, family_name, middle_name, nickname, birthdate, phone_number, phone_number_verified_at, picture, roles, revoked_timestamp, created_at, updated_at FROM %s WHERE id = '%s' LIMIT 1", KeySpace+"."+models.Collections.User, id)
err := p.db.Query(query).Consistency(gocql.One).Scan(&user.ID, &user.Email, &user.EmailVerifiedAt, &user.Password, &user.SignupMethods, &user.GivenName, &user.FamilyName, &user.MiddleName, &user.Nickname, &user.Birthdate, &user.PhoneNumber, &user.PhoneNumberVerifiedAt, &user.Picture, &user.Roles, &user.RevokedTimestamp, &user.CreatedAt, &user.UpdatedAt)
if err != nil {
return user, err
}
return user, nil
}

View File

@@ -0,0 +1,102 @@
package cassandradb
import (
"fmt"
"log"
"time"
"github.com/authorizerdev/authorizer/server/db/models"
"github.com/authorizerdev/authorizer/server/graph/model"
"github.com/gocql/gocql"
"github.com/google/uuid"
)
// AddVerification to save verification request in database
func (p *provider) AddVerificationRequest(verificationRequest models.VerificationRequest) (models.VerificationRequest, error) {
if verificationRequest.ID == "" {
verificationRequest.ID = uuid.New().String()
}
verificationRequest.CreatedAt = time.Now().Unix()
verificationRequest.UpdatedAt = time.Now().Unix()
query := fmt.Sprintf("INSERT INTO %s (id, jwt_token, identifier, expires_at, email, nonce, redirect_uri, created_at, updated_at) VALUES ('%s', '%s', '%s', %d, '%s', '%s', '%s', %d, %d)", KeySpace+"."+models.Collections.VerificationRequest, verificationRequest.ID, verificationRequest.Token, verificationRequest.Identifier, verificationRequest.ExpiresAt, verificationRequest.Email, verificationRequest.Nonce, verificationRequest.RedirectURI, verificationRequest.CreatedAt, verificationRequest.UpdatedAt)
err := p.db.Query(query).Exec()
if err != nil {
return verificationRequest, err
}
return verificationRequest, nil
}
// GetVerificationRequestByToken to get verification request from database using token
func (p *provider) GetVerificationRequestByToken(token string) (models.VerificationRequest, error) {
var verificationRequest models.VerificationRequest
query := fmt.Sprintf(`SELECT id, jwt_token, identifier, expires_at, email, nonce, redirect_uri, created_at, updated_at FROM %s WHERE jwt_token = '%s' LIMIT 1`, KeySpace+"."+models.Collections.VerificationRequest, token)
err := p.db.Query(query).Consistency(gocql.One).Scan(&verificationRequest.ID, &verificationRequest.Token, &verificationRequest.Identifier, &verificationRequest.ExpiresAt, &verificationRequest.Email, &verificationRequest.Nonce, &verificationRequest.RedirectURI, &verificationRequest.CreatedAt, &verificationRequest.UpdatedAt)
if err != nil {
return verificationRequest, err
}
return verificationRequest, nil
}
// GetVerificationRequestByEmail to get verification request by email from database
func (p *provider) GetVerificationRequestByEmail(email string, identifier string) (models.VerificationRequest, error) {
var verificationRequest models.VerificationRequest
query := fmt.Sprintf(`SELECT id, jwt_token, identifier, expires_at, email, nonce, redirect_uri, created_at, updated_at FROM %s WHERE email = '%s' AND identifier = '%s' LIMIT 1 ALLOW FILTERING`, KeySpace+"."+models.Collections.VerificationRequest, email, identifier)
err := p.db.Query(query).Consistency(gocql.One).Scan(&verificationRequest.ID, &verificationRequest.Token, &verificationRequest.Identifier, &verificationRequest.ExpiresAt, &verificationRequest.Email, &verificationRequest.Nonce, &verificationRequest.RedirectURI, &verificationRequest.CreatedAt, &verificationRequest.UpdatedAt)
if err != nil {
return verificationRequest, err
}
return verificationRequest, nil
}
// ListVerificationRequests to get list of verification requests from database
func (p *provider) ListVerificationRequests(pagination model.Pagination) (*model.VerificationRequests, error) {
var verificationRequests []*model.VerificationRequest
paginationClone := pagination
totalCountQuery := fmt.Sprintf(`SELECT COUNT(*) FROM %s`, KeySpace+"."+models.Collections.VerificationRequest)
err := p.db.Query(totalCountQuery).Consistency(gocql.One).Scan(&paginationClone.Total)
if err != nil {
log.Println("Error while quering verification request", err)
return nil, err
}
// there is no offset in cassandra
// so we fetch till limit + offset
// and return the results from offset to limit
query := fmt.Sprintf(`SELECT id, jwt_token, identifier, expires_at, email, nonce, redirect_uri, created_at, updated_at FROM %s LIMIT %d`, KeySpace+"."+models.Collections.VerificationRequest, pagination.Limit+pagination.Offset)
scanner := p.db.Query(query).Iter().Scanner()
counter := int64(0)
for scanner.Next() {
if counter >= pagination.Offset {
var verificationRequest models.VerificationRequest
err := scanner.Scan(&verificationRequest.ID, &verificationRequest.Token, &verificationRequest.Identifier, &verificationRequest.ExpiresAt, &verificationRequest.Email, &verificationRequest.Nonce, &verificationRequest.RedirectURI, &verificationRequest.CreatedAt, &verificationRequest.UpdatedAt)
if err != nil {
log.Println("Error while parsing verification request", err)
return nil, err
}
verificationRequests = append(verificationRequests, verificationRequest.AsAPIVerificationRequest())
}
counter++
}
return &model.VerificationRequests{
VerificationRequests: verificationRequests,
Pagination: &paginationClone,
}, nil
}
// DeleteVerificationRequest to delete verification request from database
func (p *provider) DeleteVerificationRequest(verificationRequest models.VerificationRequest) error {
query := fmt.Sprintf("DELETE FROM %s WHERE id = '%s'", KeySpace+"."+models.Collections.VerificationRequest, verificationRequest.ID)
err := p.db.Query(query).Exec()
if err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,32 @@
package provider_template
import (
"time"
"github.com/authorizerdev/authorizer/server/db/models"
"github.com/google/uuid"
)
// AddEnv to save environment information in database
func (p *provider) AddEnv(env models.Env) (models.Env, error) {
if env.ID == "" {
env.ID = uuid.New().String()
}
env.CreatedAt = time.Now().Unix()
env.UpdatedAt = time.Now().Unix()
return env, nil
}
// UpdateEnv to update environment information in database
func (p *provider) UpdateEnv(env models.Env) (models.Env, error) {
env.UpdatedAt = time.Now().Unix()
return env, nil
}
// GetEnv to get environment information from database
func (p *provider) GetEnv() (models.Env, error) {
var env models.Env
return env, nil
}

View File

@@ -0,0 +1,20 @@
package provider_template
import (
"gorm.io/gorm"
)
// TODO change following provider to new db provider
type provider struct {
db *gorm.DB
}
// NewProvider returns a new SQL provider
// TODO change following provider to new db provider
func NewProvider() (*provider, error) {
var sqlDB *gorm.DB
return &provider{
db: sqlDB,
}, nil
}

View File

@@ -0,0 +1,24 @@
package provider_template
import (
"time"
"github.com/authorizerdev/authorizer/server/db/models"
"github.com/google/uuid"
)
// AddSession to save session information in database
func (p *provider) AddSession(session models.Session) error {
if session.ID == "" {
session.ID = uuid.New().String()
}
session.CreatedAt = time.Now().Unix()
session.UpdatedAt = time.Now().Unix()
return nil
}
// DeleteSession to delete session information from database
func (p *provider) DeleteSession(userId string) error {
return nil
}

View File

@@ -0,0 +1,58 @@
package provider_template
import (
"strings"
"time"
"github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/db/models"
"github.com/authorizerdev/authorizer/server/envstore"
"github.com/authorizerdev/authorizer/server/graph/model"
"github.com/google/uuid"
)
// AddUser to save user information in database
func (p *provider) AddUser(user models.User) (models.User, error) {
if user.ID == "" {
user.ID = uuid.New().String()
}
if user.Roles == "" {
user.Roles = strings.Join(envstore.EnvStoreObj.GetSliceStoreEnvVariable(constants.EnvKeyDefaultRoles), ",")
}
user.CreatedAt = time.Now().Unix()
user.UpdatedAt = time.Now().Unix()
return user, nil
}
// UpdateUser to update user information in database
func (p *provider) UpdateUser(user models.User) (models.User, error) {
user.UpdatedAt = time.Now().Unix()
return user, nil
}
// DeleteUser to delete user information from database
func (p *provider) DeleteUser(user models.User) error {
return nil
}
// ListUsers to get list of users from database
func (p *provider) ListUsers(pagination model.Pagination) (*model.Users, error) {
return nil, nil
}
// GetUserByEmail to get user information from database using email address
func (p *provider) GetUserByEmail(email string) (models.User, error) {
var user models.User
return user, nil
}
// GetUserByID to get user information from database using user ID
func (p *provider) GetUserByID(id string) (models.User, error) {
var user models.User
return user, nil
}

View File

@@ -0,0 +1,45 @@
package provider_template
import (
"time"
"github.com/authorizerdev/authorizer/server/db/models"
"github.com/authorizerdev/authorizer/server/graph/model"
"github.com/google/uuid"
)
// AddVerification to save verification request in database
func (p *provider) AddVerificationRequest(verificationRequest models.VerificationRequest) (models.VerificationRequest, error) {
if verificationRequest.ID == "" {
verificationRequest.ID = uuid.New().String()
}
verificationRequest.CreatedAt = time.Now().Unix()
verificationRequest.UpdatedAt = time.Now().Unix()
return verificationRequest, nil
}
// GetVerificationRequestByToken to get verification request from database using token
func (p *provider) GetVerificationRequestByToken(token string) (models.VerificationRequest, error) {
var verificationRequest models.VerificationRequest
return verificationRequest, nil
}
// GetVerificationRequestByEmail to get verification request by email from database
func (p *provider) GetVerificationRequestByEmail(email string, identifier string) (models.VerificationRequest, error) {
var verificationRequest models.VerificationRequest
return verificationRequest, nil
}
// ListVerificationRequests to get list of verification requests from database
func (p *provider) ListVerificationRequests(pagination model.Pagination) (*model.VerificationRequests, error) {
return nil, nil
}
// DeleteVerificationRequest to delete verification request from database
func (p *provider) DeleteVerificationRequest(verificationRequest models.VerificationRequest) error {
return nil
}

View File

@@ -107,7 +107,7 @@ func InviteEmail(toEmail, token, verificationURL, redirectURI string) error {
err := SendMail(Receiver, Subject, message) err := SendMail(Receiver, Subject, message)
if err != nil { if err != nil {
log.Println("=> error sending email:", err) log.Println("error sending email:", err)
} }
return err return err
} }

View File

@@ -107,7 +107,7 @@ func SendVerificationMail(toEmail, token, hostname string) error {
err := SendMail(Receiver, Subject, message) err := SendMail(Receiver, Subject, message)
if err != nil { if err != nil {
log.Println("=> error sending email:", err) log.Println("error sending email:", err)
} }
return err return err
} }

21
server/env/env.go vendored
View File

@@ -38,6 +38,13 @@ func InitRequiredEnv() error {
dbURL := os.Getenv(constants.EnvKeyDatabaseURL) dbURL := os.Getenv(constants.EnvKeyDatabaseURL)
dbType := os.Getenv(constants.EnvKeyDatabaseType) dbType := os.Getenv(constants.EnvKeyDatabaseType)
dbName := os.Getenv(constants.EnvKeyDatabaseName) dbName := os.Getenv(constants.EnvKeyDatabaseName)
dbPort := os.Getenv(constants.EnvKeyDatabasePort)
dbHost := os.Getenv(constants.EnvKeyDatabaseHost)
dbUsername := os.Getenv(constants.EnvKeyDatabaseUsername)
dbPassword := os.Getenv(constants.EnvKeyDatabasePassword)
dbCert := os.Getenv(constants.EnvKeyDatabaseCert)
dbCertKey := os.Getenv(constants.EnvKeyDatabaseCertKey)
dbCACert := os.Getenv(constants.EnvKeyDatabaseCACert)
if strings.TrimSpace(dbType) == "" { if strings.TrimSpace(dbType) == "" {
if envstore.ARG_DB_TYPE != nil && *envstore.ARG_DB_TYPE != "" { if envstore.ARG_DB_TYPE != nil && *envstore.ARG_DB_TYPE != "" {
@@ -54,7 +61,7 @@ func InitRequiredEnv() error {
dbURL = strings.TrimSpace(*envstore.ARG_DB_URL) dbURL = strings.TrimSpace(*envstore.ARG_DB_URL)
} }
if dbURL == "" { if dbURL == "" && dbPort == "" && dbHost == "" && dbUsername == "" && dbPassword == "" {
return errors.New("invalid database url. DATABASE_URL is required") return errors.New("invalid database url. DATABASE_URL is required")
} }
} }
@@ -69,6 +76,14 @@ func InitRequiredEnv() error {
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabaseURL, dbURL) envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabaseURL, dbURL)
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabaseType, dbType) envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabaseType, dbType)
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabaseName, dbName) envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabaseName, dbName)
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabaseHost, dbHost)
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabasePort, dbPort)
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabaseUsername, dbUsername)
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabasePassword, dbPassword)
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabaseCert, dbCert)
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabaseCertKey, dbCertKey)
envstore.EnvStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyDatabaseCACert, dbCACert)
return nil return nil
} }
@@ -113,6 +128,10 @@ func InitAllEnv() error {
envData.StringEnv[constants.EnvKeyAppURL] = os.Getenv(constants.EnvKeyAppURL) envData.StringEnv[constants.EnvKeyAppURL] = os.Getenv(constants.EnvKeyAppURL)
} }
if envData.StringEnv[constants.EnvKeyAuthorizerURL] == "" {
envData.StringEnv[constants.EnvKeyAuthorizerURL] = os.Getenv(constants.EnvKeyAuthorizerURL)
}
if envData.StringEnv[constants.EnvKeyPort] == "" { if envData.StringEnv[constants.EnvKeyPort] == "" {
envData.StringEnv[constants.EnvKeyPort] = os.Getenv(constants.EnvKeyPort) envData.StringEnv[constants.EnvKeyPort] = os.Getenv(constants.EnvKeyPort)
if envData.StringEnv[constants.EnvKeyPort] == "" { if envData.StringEnv[constants.EnvKeyPort] == "" {

View File

@@ -9,6 +9,7 @@ require (
github.com/gin-gonic/gin v1.7.2 github.com/gin-gonic/gin v1.7.2
github.com/go-playground/validator/v10 v10.8.0 // indirect github.com/go-playground/validator/v10 v10.8.0 // indirect
github.com/go-redis/redis/v8 v8.11.0 github.com/go-redis/redis/v8 v8.11.0
github.com/gocql/gocql v1.0.0
github.com/golang-jwt/jwt v3.2.2+incompatible github.com/golang-jwt/jwt v3.2.2+incompatible
github.com/golang/protobuf v1.5.2 // indirect github.com/golang/protobuf v1.5.2 // indirect
github.com/google/uuid v1.3.0 github.com/google/uuid v1.3.0

View File

@@ -48,6 +48,10 @@ github.com/arangodb/go-velocypack v0.0.0-20200318135517-5af53c29c67e h1:Xg+hGrY2
github.com/arangodb/go-velocypack v0.0.0-20200318135517-5af53c29c67e/go.mod h1:mq7Shfa/CaixoDxiyAAc5jZ6CVBAyPaNQCGS7mkj4Ho= github.com/arangodb/go-velocypack v0.0.0-20200318135517-5af53c29c67e/go.mod h1:mq7Shfa/CaixoDxiyAAc5jZ6CVBAyPaNQCGS7mkj4Ho=
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q= github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q=
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE= github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE=
github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932 h1:mXoPYz/Ul5HYEDvkta6I8/rnYM5gSdSV2tJ6XbZuEtY=
github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k=
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY=
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -106,6 +110,8 @@ github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfC
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gocql/gocql v1.0.0 h1:UnbTERpP72VZ/viKE1Q1gPtmLvyTZTvuAstvSRydw/c=
github.com/gocql/gocql v1.0.0/go.mod h1:3gM2c4D3AnkISwBxGnMMsS8Oy4y2lhbPRsH4xnJrHG8=
github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw= github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw=
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
@@ -140,8 +146,9 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA=
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
@@ -175,6 +182,8 @@ github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f/go.mod h1:kBGZzfjB
github.com/gorilla/mux v1.6.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.6.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8=
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
@@ -677,6 +686,8 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/mail.v2 v2.3.1 h1:WYFn/oANrAGP2C0dcV6/pbkPzv8yGzqTjPmTeO7qoXk= gopkg.in/mail.v2 v2.3.1 h1:WYFn/oANrAGP2C0dcV6/pbkPzv8yGzqTjPmTeO7qoXk=
gopkg.in/mail.v2 v2.3.1/go.mod h1:htwXN1Qh09vZJ1NVKxQqHPBaCBbzKhp5GzuJEA4VJWw= gopkg.in/mail.v2 v2.3.1/go.mod h1:htwXN1Qh09vZJ1NVKxQqHPBaCBbzKhp5GzuJEA4VJWw=
gopkg.in/readline.v1 v1.0.0-20160726135117-62c6fe619375/go.mod h1:lNEQeAhU009zbRxng+XOj5ITVgY24WcbNnQopyfKoYQ= gopkg.in/readline.v1 v1.0.0-20160726135117-62c6fe619375/go.mod h1:lNEQeAhU009zbRxng+XOj5ITVgY24WcbNnQopyfKoYQ=

View File

@@ -61,9 +61,13 @@ type ComplexityRoot struct {
ClientSecret func(childComplexity int) int ClientSecret func(childComplexity int) int
CookieName func(childComplexity int) int CookieName func(childComplexity int) int
CustomAccessTokenScript func(childComplexity int) int CustomAccessTokenScript func(childComplexity int) int
DatabaseHost func(childComplexity int) int
DatabaseName func(childComplexity int) int DatabaseName func(childComplexity int) int
DatabasePassword func(childComplexity int) int
DatabasePort func(childComplexity int) int
DatabaseType func(childComplexity int) int DatabaseType func(childComplexity int) int
DatabaseURL func(childComplexity int) int DatabaseURL func(childComplexity int) int
DatabaseUsername func(childComplexity int) int
DefaultRoles func(childComplexity int) int DefaultRoles func(childComplexity int) int
DisableBasicAuthentication func(childComplexity int) int DisableBasicAuthentication func(childComplexity int) int
DisableEmailVerification func(childComplexity int) int DisableEmailVerification func(childComplexity int) int
@@ -356,6 +360,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.Env.CustomAccessTokenScript(childComplexity), true return e.complexity.Env.CustomAccessTokenScript(childComplexity), true
case "Env.DATABASE_HOST":
if e.complexity.Env.DatabaseHost == nil {
break
}
return e.complexity.Env.DatabaseHost(childComplexity), true
case "Env.DATABASE_NAME": case "Env.DATABASE_NAME":
if e.complexity.Env.DatabaseName == nil { if e.complexity.Env.DatabaseName == nil {
break break
@@ -363,6 +374,20 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.Env.DatabaseName(childComplexity), true return e.complexity.Env.DatabaseName(childComplexity), true
case "Env.DATABASE_PASSWORD":
if e.complexity.Env.DatabasePassword == nil {
break
}
return e.complexity.Env.DatabasePassword(childComplexity), true
case "Env.DATABASE_PORT":
if e.complexity.Env.DatabasePort == nil {
break
}
return e.complexity.Env.DatabasePort(childComplexity), true
case "Env.DATABASE_TYPE": case "Env.DATABASE_TYPE":
if e.complexity.Env.DatabaseType == nil { if e.complexity.Env.DatabaseType == nil {
break break
@@ -377,6 +402,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.Env.DatabaseURL(childComplexity), true return e.complexity.Env.DatabaseURL(childComplexity), true
case "Env.DATABASE_USERNAME":
if e.complexity.Env.DatabaseUsername == nil {
break
}
return e.complexity.Env.DatabaseUsername(childComplexity), true
case "Env.DEFAULT_ROLES": case "Env.DEFAULT_ROLES":
if e.complexity.Env.DefaultRoles == nil { if e.complexity.Env.DefaultRoles == nil {
break break
@@ -1394,6 +1426,10 @@ type Env {
DATABASE_NAME: String! DATABASE_NAME: String!
DATABASE_URL: String! DATABASE_URL: String!
DATABASE_TYPE: String! DATABASE_TYPE: String!
DATABASE_USERNAME: String!
DATABASE_PASSWORD: String!
DATABASE_HOST: String!
DATABASE_PORT: String!
CLIENT_ID: String! CLIENT_ID: String!
CLIENT_SECRET: String! CLIENT_SECRET: String!
CUSTOM_ACCESS_TOKEN_SCRIPT: String CUSTOM_ACCESS_TOKEN_SCRIPT: String
@@ -2400,6 +2436,146 @@ func (ec *executionContext) _Env_DATABASE_TYPE(ctx context.Context, field graphq
return ec.marshalNString2string(ctx, field.Selections, res) return ec.marshalNString2string(ctx, field.Selections, res)
} }
func (ec *executionContext) _Env_DATABASE_USERNAME(ctx context.Context, field graphql.CollectedField, obj *model.Env) (ret graphql.Marshaler) {
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
ret = graphql.Null
}
}()
fc := &graphql.FieldContext{
Object: "Env",
Field: field,
Args: nil,
IsMethod: false,
IsResolver: false,
}
ctx = graphql.WithFieldContext(ctx, fc)
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
return obj.DatabaseUsername, nil
})
if err != nil {
ec.Error(ctx, err)
return graphql.Null
}
if resTmp == nil {
if !graphql.HasFieldError(ctx, fc) {
ec.Errorf(ctx, "must not be null")
}
return graphql.Null
}
res := resTmp.(string)
fc.Result = res
return ec.marshalNString2string(ctx, field.Selections, res)
}
func (ec *executionContext) _Env_DATABASE_PASSWORD(ctx context.Context, field graphql.CollectedField, obj *model.Env) (ret graphql.Marshaler) {
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
ret = graphql.Null
}
}()
fc := &graphql.FieldContext{
Object: "Env",
Field: field,
Args: nil,
IsMethod: false,
IsResolver: false,
}
ctx = graphql.WithFieldContext(ctx, fc)
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
return obj.DatabasePassword, nil
})
if err != nil {
ec.Error(ctx, err)
return graphql.Null
}
if resTmp == nil {
if !graphql.HasFieldError(ctx, fc) {
ec.Errorf(ctx, "must not be null")
}
return graphql.Null
}
res := resTmp.(string)
fc.Result = res
return ec.marshalNString2string(ctx, field.Selections, res)
}
func (ec *executionContext) _Env_DATABASE_HOST(ctx context.Context, field graphql.CollectedField, obj *model.Env) (ret graphql.Marshaler) {
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
ret = graphql.Null
}
}()
fc := &graphql.FieldContext{
Object: "Env",
Field: field,
Args: nil,
IsMethod: false,
IsResolver: false,
}
ctx = graphql.WithFieldContext(ctx, fc)
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
return obj.DatabaseHost, nil
})
if err != nil {
ec.Error(ctx, err)
return graphql.Null
}
if resTmp == nil {
if !graphql.HasFieldError(ctx, fc) {
ec.Errorf(ctx, "must not be null")
}
return graphql.Null
}
res := resTmp.(string)
fc.Result = res
return ec.marshalNString2string(ctx, field.Selections, res)
}
func (ec *executionContext) _Env_DATABASE_PORT(ctx context.Context, field graphql.CollectedField, obj *model.Env) (ret graphql.Marshaler) {
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
ret = graphql.Null
}
}()
fc := &graphql.FieldContext{
Object: "Env",
Field: field,
Args: nil,
IsMethod: false,
IsResolver: false,
}
ctx = graphql.WithFieldContext(ctx, fc)
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
return obj.DatabasePort, nil
})
if err != nil {
ec.Error(ctx, err)
return graphql.Null
}
if resTmp == nil {
if !graphql.HasFieldError(ctx, fc) {
ec.Errorf(ctx, "must not be null")
}
return graphql.Null
}
res := resTmp.(string)
fc.Result = res
return ec.marshalNString2string(ctx, field.Selections, res)
}
func (ec *executionContext) _Env_CLIENT_ID(ctx context.Context, field graphql.CollectedField, obj *model.Env) (ret graphql.Marshaler) { func (ec *executionContext) _Env_CLIENT_ID(ctx context.Context, field graphql.CollectedField, obj *model.Env) (ret graphql.Marshaler) {
defer func() { defer func() {
if r := recover(); r != nil { if r := recover(); r != nil {
@@ -8780,6 +8956,26 @@ func (ec *executionContext) _Env(ctx context.Context, sel ast.SelectionSet, obj
if out.Values[i] == graphql.Null { if out.Values[i] == graphql.Null {
invalids++ invalids++
} }
case "DATABASE_USERNAME":
out.Values[i] = ec._Env_DATABASE_USERNAME(ctx, field, obj)
if out.Values[i] == graphql.Null {
invalids++
}
case "DATABASE_PASSWORD":
out.Values[i] = ec._Env_DATABASE_PASSWORD(ctx, field, obj)
if out.Values[i] == graphql.Null {
invalids++
}
case "DATABASE_HOST":
out.Values[i] = ec._Env_DATABASE_HOST(ctx, field, obj)
if out.Values[i] == graphql.Null {
invalids++
}
case "DATABASE_PORT":
out.Values[i] = ec._Env_DATABASE_PORT(ctx, field, obj)
if out.Values[i] == graphql.Null {
invalids++
}
case "CLIENT_ID": case "CLIENT_ID":
out.Values[i] = ec._Env_CLIENT_ID(ctx, field, obj) out.Values[i] = ec._Env_CLIENT_ID(ctx, field, obj)
if out.Values[i] == graphql.Null { if out.Values[i] == graphql.Null {

View File

@@ -29,6 +29,10 @@ type Env struct {
DatabaseName string `json:"DATABASE_NAME"` DatabaseName string `json:"DATABASE_NAME"`
DatabaseURL string `json:"DATABASE_URL"` DatabaseURL string `json:"DATABASE_URL"`
DatabaseType string `json:"DATABASE_TYPE"` DatabaseType string `json:"DATABASE_TYPE"`
DatabaseUsername string `json:"DATABASE_USERNAME"`
DatabasePassword string `json:"DATABASE_PASSWORD"`
DatabaseHost string `json:"DATABASE_HOST"`
DatabasePort string `json:"DATABASE_PORT"`
ClientID string `json:"CLIENT_ID"` ClientID string `json:"CLIENT_ID"`
ClientSecret string `json:"CLIENT_SECRET"` ClientSecret string `json:"CLIENT_SECRET"`
CustomAccessTokenScript *string `json:"CUSTOM_ACCESS_TOKEN_SCRIPT"` CustomAccessTokenScript *string `json:"CUSTOM_ACCESS_TOKEN_SCRIPT"`

View File

@@ -92,6 +92,10 @@ type Env {
DATABASE_NAME: String! DATABASE_NAME: String!
DATABASE_URL: String! DATABASE_URL: String!
DATABASE_TYPE: String! DATABASE_TYPE: String!
DATABASE_USERNAME: String!
DATABASE_PASSWORD: String!
DATABASE_HOST: String!
DATABASE_PORT: String!
CLIENT_ID: String! CLIENT_ID: String!
CLIENT_SECRET: String! CLIENT_SECRET: String!
CUSTOM_ACCESS_TOKEN_SCRIPT: String CUSTOM_ACCESS_TOKEN_SCRIPT: String

View File

@@ -174,7 +174,11 @@ func OAuthCallbackHandler() gin.HandlerFunc {
sessionstore.SetState(authToken.RefreshToken.Token, authToken.FingerPrint+"@"+user.ID) sessionstore.SetState(authToken.RefreshToken.Token, authToken.FingerPrint+"@"+user.ID)
} }
go utils.SaveSessionInDB(c, user.ID) go db.Provider.AddSession(models.Session{
UserID: user.ID,
UserAgent: utils.GetUserAgent(c.Request),
IP: utils.GetIP(c.Request),
})
if strings.Contains(redirectURL, "?") { if strings.Contains(redirectURL, "?") {
redirectURL = redirectURL + "&" + params redirectURL = redirectURL + "&" + params
} else { } else {
@@ -259,7 +263,7 @@ func processGithubUserInfo(code string) (models.User, error) {
GivenName: &firstName, GivenName: &firstName,
FamilyName: &lastName, FamilyName: &lastName,
Picture: &picture, Picture: &picture,
Email: userRawData["sub"], Email: userRawData["email"],
} }
return user, nil return user, nil

View File

@@ -8,6 +8,7 @@ import (
"github.com/authorizerdev/authorizer/server/cookie" "github.com/authorizerdev/authorizer/server/cookie"
"github.com/authorizerdev/authorizer/server/db" "github.com/authorizerdev/authorizer/server/db"
"github.com/authorizerdev/authorizer/server/db/models"
"github.com/authorizerdev/authorizer/server/sessionstore" "github.com/authorizerdev/authorizer/server/sessionstore"
"github.com/authorizerdev/authorizer/server/token" "github.com/authorizerdev/authorizer/server/token"
"github.com/authorizerdev/authorizer/server/utils" "github.com/authorizerdev/authorizer/server/utils"
@@ -109,7 +110,11 @@ func VerifyEmailHandler() gin.HandlerFunc {
redirectURL = redirectURL + "?" + params redirectURL = redirectURL + "?" + params
} }
go utils.SaveSessionInDB(c, user.ID) go db.Provider.AddSession(models.Session{
UserID: user.ID,
UserAgent: utils.GetUserAgent(c.Request),
IP: utils.GetIP(c.Request),
})
c.Redirect(http.StatusTemporaryRedirect, redirectURL) c.Redirect(http.StatusTemporaryRedirect, redirectURL)
} }

View File

@@ -15,7 +15,7 @@ func CORSMiddleware() gin.HandlerFunc {
} }
c.Writer.Header().Set("Access-Control-Allow-Credentials", "true") c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With") c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With, X-authorizer-url")
c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS, GET, PUT") c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS, GET, PUT")
if c.Request.Method == "OPTIONS" { if c.Request.Method == "OPTIONS" {

View File

@@ -34,6 +34,10 @@ func EnvResolver(ctx context.Context) (*model.Env, error) {
databaseURL := store.StringEnv[constants.EnvKeyDatabaseURL] databaseURL := store.StringEnv[constants.EnvKeyDatabaseURL]
databaseName := store.StringEnv[constants.EnvKeyDatabaseName] databaseName := store.StringEnv[constants.EnvKeyDatabaseName]
databaseType := store.StringEnv[constants.EnvKeyDatabaseType] databaseType := store.StringEnv[constants.EnvKeyDatabaseType]
databaseUsername := store.StringEnv[constants.EnvKeyDatabaseUsername]
databasePassword := store.StringEnv[constants.EnvKeyDatabasePassword]
databaseHost := store.StringEnv[constants.EnvKeyDatabaseHost]
databasePort := store.StringEnv[constants.EnvKeyDatabasePort]
customAccessTokenScript := store.StringEnv[constants.EnvKeyCustomAccessTokenScript] customAccessTokenScript := store.StringEnv[constants.EnvKeyCustomAccessTokenScript]
smtpHost := store.StringEnv[constants.EnvKeySmtpHost] smtpHost := store.StringEnv[constants.EnvKeySmtpHost]
smtpPort := store.StringEnv[constants.EnvKeySmtpPort] smtpPort := store.StringEnv[constants.EnvKeySmtpPort]
@@ -77,6 +81,10 @@ func EnvResolver(ctx context.Context) (*model.Env, error) {
DatabaseName: databaseName, DatabaseName: databaseName,
DatabaseURL: databaseURL, DatabaseURL: databaseURL,
DatabaseType: databaseType, DatabaseType: databaseType,
DatabaseUsername: databaseUsername,
DatabasePassword: databasePassword,
DatabaseHost: databaseHost,
DatabasePort: databasePort,
ClientID: clientID, ClientID: clientID,
ClientSecret: clientSecret, ClientSecret: clientSecret,
CustomAccessTokenScript: &customAccessTokenScript, CustomAccessTokenScript: &customAccessTokenScript,

View File

@@ -10,6 +10,7 @@ import (
"github.com/authorizerdev/authorizer/server/constants" "github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/cookie" "github.com/authorizerdev/authorizer/server/cookie"
"github.com/authorizerdev/authorizer/server/db" "github.com/authorizerdev/authorizer/server/db"
"github.com/authorizerdev/authorizer/server/db/models"
"github.com/authorizerdev/authorizer/server/envstore" "github.com/authorizerdev/authorizer/server/envstore"
"github.com/authorizerdev/authorizer/server/graph/model" "github.com/authorizerdev/authorizer/server/graph/model"
"github.com/authorizerdev/authorizer/server/sessionstore" "github.com/authorizerdev/authorizer/server/sessionstore"
@@ -96,7 +97,11 @@ func LoginResolver(ctx context.Context, params model.LoginInput) (*model.AuthRes
sessionstore.SetState(authToken.RefreshToken.Token, authToken.FingerPrint+"@"+user.ID) sessionstore.SetState(authToken.RefreshToken.Token, authToken.FingerPrint+"@"+user.ID)
} }
go utils.SaveSessionInDB(gc, user.ID) go db.Provider.AddSession(models.Session{
UserID: user.ID,
UserAgent: utils.GetUserAgent(gc.Request),
IP: utils.GetIP(gc.Request),
})
return res, nil return res, nil
} }

View File

@@ -174,7 +174,11 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR
sessionstore.SetState(authToken.FingerPrintHash, authToken.FingerPrint+"@"+user.ID) sessionstore.SetState(authToken.FingerPrintHash, authToken.FingerPrint+"@"+user.ID)
cookie.SetSession(gc, authToken.FingerPrintHash) cookie.SetSession(gc, authToken.FingerPrintHash)
go utils.SaveSessionInDB(gc, user.ID) go db.Provider.AddSession(models.Session{
UserID: user.ID,
UserAgent: utils.GetUserAgent(gc.Request),
IP: utils.GetIP(gc.Request),
})
expiresIn := authToken.AccessToken.ExpiresAt - time.Now().Unix() expiresIn := authToken.AccessToken.ExpiresAt - time.Now().Unix()
if expiresIn <= 0 { if expiresIn <= 0 {

View File

@@ -8,6 +8,7 @@ import (
"github.com/authorizerdev/authorizer/server/cookie" "github.com/authorizerdev/authorizer/server/cookie"
"github.com/authorizerdev/authorizer/server/db" "github.com/authorizerdev/authorizer/server/db"
"github.com/authorizerdev/authorizer/server/db/models"
"github.com/authorizerdev/authorizer/server/graph/model" "github.com/authorizerdev/authorizer/server/graph/model"
"github.com/authorizerdev/authorizer/server/sessionstore" "github.com/authorizerdev/authorizer/server/sessionstore"
"github.com/authorizerdev/authorizer/server/token" "github.com/authorizerdev/authorizer/server/token"
@@ -62,7 +63,11 @@ func VerifyEmailResolver(ctx context.Context, params model.VerifyEmailInput) (*m
sessionstore.SetState(authToken.FingerPrintHash, authToken.FingerPrint+"@"+user.ID) sessionstore.SetState(authToken.FingerPrintHash, authToken.FingerPrint+"@"+user.ID)
sessionstore.SetState(authToken.AccessToken.Token, authToken.FingerPrint+"@"+user.ID) sessionstore.SetState(authToken.AccessToken.Token, authToken.FingerPrint+"@"+user.ID)
cookie.SetSession(gc, authToken.FingerPrintHash) cookie.SetSession(gc, authToken.FingerPrintHash)
go utils.SaveSessionInDB(gc, user.ID) go db.Provider.AddSession(models.Session{
UserID: user.ID,
UserAgent: utils.GetUserAgent(gc.Request),
IP: utils.GetIP(gc.Request),
})
expiresIn := authToken.AccessToken.ExpiresAt - time.Now().Unix() expiresIn := authToken.AccessToken.ExpiresAt - time.Now().Unix()
if expiresIn <= 0 { if expiresIn <= 0 {

View File

@@ -15,9 +15,9 @@ import (
func enableAccessTest(t *testing.T, s TestSetup) { func enableAccessTest(t *testing.T, s TestSetup) {
t.Helper() t.Helper()
t.Run(`should revoke access`, func(t *testing.T) { t.Run(`should enable access`, func(t *testing.T) {
req, ctx := createContext(s) req, ctx := createContext(s)
email := "revoke_access." + s.TestInfo.Email email := "enable_access." + s.TestInfo.Email
_, err := resolvers.MagicLinkLoginResolver(ctx, model.MagicLinkLoginInput{ _, err := resolvers.MagicLinkLoginResolver(ctx, model.MagicLinkLoginInput{
Email: email, Email: email,
}) })
@@ -45,7 +45,7 @@ func enableAccessTest(t *testing.T, s TestSetup) {
assert.NoError(t, err) assert.NoError(t, err)
assert.NotEmpty(t, res.Message) assert.NotEmpty(t, res.Message)
// it should allow login with revoked access // it should allow login with enabled access
res, err = resolvers.MagicLinkLoginResolver(ctx, model.MagicLinkLoginInput{ res, err = resolvers.MagicLinkLoginResolver(ctx, model.MagicLinkLoginInput{
Email: email, Email: email,
}) })

View File

@@ -11,9 +11,10 @@ import (
func TestResolvers(t *testing.T) { func TestResolvers(t *testing.T) {
databases := map[string]string{ databases := map[string]string{
constants.DbTypeSqlite: "../../data.db", // constants.DbTypeSqlite: "../../data.db",
// constants.DbTypeArangodb: "http://localhost:8529", // constants.DbTypeArangodb: "http://localhost:8529",
// constants.DbTypeMongodb: "mongodb://localhost:27017", // constants.DbTypeMongodb: "mongodb://localhost:27017",
constants.DbTypeCassandraDB: "127.0.0.1:9042",
} }
for dbType, dbURL := range databases { for dbType, dbURL := range databases {

View File

@@ -31,26 +31,31 @@ type TestSetup struct {
} }
func cleanData(email string) { func cleanData(email string) {
verificationRequest, err := db.Provider.GetVerificationRequestByEmail(email, constants.VerificationTypeBasicAuthSignup) // verificationRequest, err := db.Provider.GetVerificationRequestByEmail(email, constants.VerificationTypeBasicAuthSignup)
if err == nil { // if err == nil {
err = db.Provider.DeleteVerificationRequest(verificationRequest) // err = db.Provider.DeleteVerificationRequest(verificationRequest)
} // }
verificationRequest, err = db.Provider.GetVerificationRequestByEmail(email, constants.VerificationTypeForgotPassword) // verificationRequest, err = db.Provider.GetVerificationRequestByEmail(email, constants.VerificationTypeForgotPassword)
if err == nil { // if err == nil {
err = db.Provider.DeleteVerificationRequest(verificationRequest) // err = db.Provider.DeleteVerificationRequest(verificationRequest)
} // }
verificationRequest, err = db.Provider.GetVerificationRequestByEmail(email, constants.VerificationTypeUpdateEmail) // verificationRequest, err = db.Provider.GetVerificationRequestByEmail(email, constants.VerificationTypeUpdateEmail)
if err == nil { // if err == nil {
err = db.Provider.DeleteVerificationRequest(verificationRequest) // err = db.Provider.DeleteVerificationRequest(verificationRequest)
} // }
dbUser, err := db.Provider.GetUserByEmail(email) // verificationRequest, err = db.Provider.GetVerificationRequestByEmail(email, constants.VerificationTypeMagicLinkLogin)
if err == nil { // if err == nil {
db.Provider.DeleteUser(dbUser) // err = db.Provider.DeleteVerificationRequest(verificationRequest)
db.Provider.DeleteSession(dbUser.ID) // }
}
// dbUser, err := db.Provider.GetUserByEmail(email)
// if err == nil {
// db.Provider.DeleteUser(dbUser)
// db.Provider.DeleteSession(dbUser.ID)
// }
} }
func createContext(s TestSetup) (*http.Request, context.Context) { func createContext(s TestSetup) (*http.Request, context.Context) {

View File

@@ -4,7 +4,6 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"log" "log"
"os"
"strings" "strings"
"time" "time"
@@ -318,7 +317,7 @@ func CreateIDToken(user models.User, roles []string, hostname, nonce string) (st
} }
// check for the extra access token script // check for the extra access token script
accessTokenScript := os.Getenv(constants.EnvKeyCustomAccessTokenScript) accessTokenScript := envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyCustomAccessTokenScript)
if accessTokenScript != "" { if accessTokenScript != "" {
vm := otto.New() vm := otto.New()

View File

@@ -1,12 +1,7 @@
package utils package utils
import ( import (
"log"
"reflect" "reflect"
"github.com/authorizerdev/authorizer/server/db"
"github.com/authorizerdev/authorizer/server/db/models"
"github.com/gin-gonic/gin"
) )
// StringSliceContains checks if a string slice contains a particular string // StringSliceContains checks if a string slice contains a particular string
@@ -19,23 +14,6 @@ func StringSliceContains(s []string, e string) bool {
return false return false
} }
// SaveSessionInDB saves sessions generated for a given user with meta information
// Do not store token here as that could be security breach
func SaveSessionInDB(c *gin.Context, userId string) {
sessionData := models.Session{
UserID: userId,
UserAgent: GetUserAgent(c.Request),
IP: GetIP(c.Request),
}
err := db.Provider.AddSession(sessionData)
if err != nil {
log.Println("=> error saving session in db:", err)
} else {
log.Println("=> session saved in db:", sessionData)
}
}
// RemoveDuplicateString removes duplicate strings from a string slice // RemoveDuplicateString removes duplicate strings from a string slice
func RemoveDuplicateString(strSlice []string) []string { func RemoveDuplicateString(strSlice []string) []string {
allKeys := make(map[string]bool) allKeys := make(map[string]bool)

48
server/utils/file.go Normal file
View File

@@ -0,0 +1,48 @@
package utils
import (
"errors"
"os"
)
// CreateFolder creates a folder in Current working dir
func CreateFolder(dir string) (string, error) {
pwd, err := os.Getwd()
if err != nil {
return "", err
}
path := pwd + "/" + dir
err = os.Mkdir(path, 0o755)
if err == nil {
return path, nil
}
if os.IsExist(err) {
// check that the existing path is a directory
info, err := os.Stat(path)
if err != nil {
return "", err
}
if !info.IsDir() {
return "", errors.New("path exists but is not a directory")
}
return path, nil
}
return path, err
}
// CreateFile creates a file on given path with given content
func CreateFile(filePath string, content string) error {
f, err := os.Create(filePath)
if err != nil {
return err
}
defer f.Close()
_, err = f.WriteString(content)
if err != nil {
return err
}
return nil
}

View File

@@ -10,7 +10,20 @@ import (
) )
// GetHost returns hostname from request context // GetHost returns hostname from request context
// if X-Authorizer-URL header is set it is given highest priority
// if EnvKeyAuthorizerURL is set it is given second highest priority.
// if above 2 are not set the requesting host name is used
func GetHost(c *gin.Context) string { func GetHost(c *gin.Context) string {
authorizerURL := c.Request.Header.Get("X-Authorizer-URL")
if authorizerURL != "" {
return authorizerURL
}
authorizerURL = envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAuthorizerURL)
if authorizerURL != "" {
return authorizerURL
}
scheme := c.Request.Header.Get("X-Forwarded-Proto") scheme := c.Request.Header.Get("X-Forwarded-Proto")
if scheme != "https" { if scheme != "https" {
scheme = "http" scheme = "http"