feat: login wall (#42)
* feat: add login-wall app * fix: rename vars * fix: rename vars * update docker file * add validations for app state * add host check for app * fix: docker file
This commit is contained in:
parent
d1973c1f8f
commit
f88363e6dc
|
@ -4,3 +4,5 @@ server/server
|
|||
.gitignore
|
||||
README.md
|
||||
ROADMAP.md
|
||||
build
|
||||
.env
|
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -1,3 +1,6 @@
|
|||
server/server
|
||||
server/.env
|
||||
data
|
||||
app/node_modules
|
||||
build
|
||||
.env
|
13
Dockerfile
13
Dockerfile
|
@ -1,19 +1,20 @@
|
|||
FROM golang:1.16-alpine as builder
|
||||
WORKDIR /app
|
||||
COPY . .
|
||||
COPY server server
|
||||
COPY Makefile .
|
||||
|
||||
ARG VERSION=0.1.0-beta.0
|
||||
ENV VERSION="${VERSION}"
|
||||
|
||||
RUN apk add build-base &&\
|
||||
cd server && \
|
||||
go mod download && \
|
||||
make clean && make && \
|
||||
chmod 777 server
|
||||
chmod 777 build/server
|
||||
|
||||
FROM alpine:latest
|
||||
RUN apk --no-cache add ca-certificates
|
||||
WORKDIR /root/
|
||||
COPY --from=builder /app/server/server .
|
||||
COPY app app
|
||||
COPY templates templates
|
||||
COPY --from=builder /app/build build
|
||||
EXPOSE 8080
|
||||
CMD [ "./server" ]
|
||||
CMD [ "./build/server" ]
|
||||
|
|
7
Makefile
Normal file
7
Makefile
Normal file
|
@ -0,0 +1,7 @@
|
|||
DEFAULT_VERSION=0.1.0-local
|
||||
VERSION := $(or $(VERSION),$(DEFAULT_VERSION))
|
||||
|
||||
cmd:
|
||||
cd server && go build -ldflags "-w -X main.Version=$(VERSION)" -o '../build/server'
|
||||
clean:
|
||||
rm -rf build
|
2
TODO.md
2
TODO.md
|
@ -1,2 +0,0 @@
|
|||
- [] Add env to disalbe email verification -> this can be helpful while onboarding user
|
||||
- []
|
3
app/README.md
Normal file
3
app/README.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
# Authorizer APP
|
||||
|
||||
App that can be used as login wall for your any application in combination with @authorizerdev/@authorizer.js
|
16
app/build/bundle.css
Normal file
16
app/build/bundle.css
Normal file
|
@ -0,0 +1,16 @@
|
|||
body {
|
||||
margin: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
||||
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
||||
sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
color: #374151;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
*,
|
||||
*:before,
|
||||
*:after {
|
||||
box-sizing: inherit;
|
||||
}
|
275
app/build/bundle.js
Normal file
275
app/build/bundle.js
Normal file
File diff suppressed because one or more lines are too long
7
app/build/bundle.js.map
Normal file
7
app/build/bundle.js.map
Normal file
File diff suppressed because one or more lines are too long
1402
app/package-lock.json
generated
Normal file
1402
app/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
25
app/package.json
Normal file
25
app/package.json
Normal file
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"name": "app",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"build": "esbuild src/index.tsx --bundle --minify --sourcemap --outfile=build/bundle.js"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "Lakhan Samani",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@authorizerdev/authorizer-react": "^0.1.0-beta.6",
|
||||
"@types/react": "^17.0.15",
|
||||
"@types/react-dom": "^17.0.9",
|
||||
"esbuild": "^0.12.17",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-router-dom": "^5.2.0",
|
||||
"typescript": "^4.3.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react-router-dom": "^5.1.8"
|
||||
}
|
||||
}
|
33
app/src/App.tsx
Normal file
33
app/src/App.tsx
Normal file
|
@ -0,0 +1,33 @@
|
|||
import React from 'react';
|
||||
import { BrowserRouter } from 'react-router-dom';
|
||||
import { AuthorizerProvider } from '@authorizerdev/authorizer-react';
|
||||
import Root from './Root';
|
||||
|
||||
export default function App() {
|
||||
// @ts-ignore
|
||||
const globalState: Record<string, string> = window['__authorizer__'];
|
||||
return (
|
||||
<div style={{ display: 'flex', justifyContent: 'center' }}>
|
||||
<div
|
||||
style={{
|
||||
width: 400,
|
||||
margin: `10px auto`,
|
||||
border: `1px solid #D1D5DB`,
|
||||
padding: `25px 20px`,
|
||||
borderRadius: 5,
|
||||
}}
|
||||
>
|
||||
<BrowserRouter>
|
||||
<AuthorizerProvider
|
||||
config={{
|
||||
authorizerURL: globalState.authorizerURL,
|
||||
redirectURL: globalState.redirectURL,
|
||||
}}
|
||||
>
|
||||
<Root />
|
||||
</AuthorizerProvider>
|
||||
</BrowserRouter>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
35
app/src/Root.tsx
Normal file
35
app/src/Root.tsx
Normal file
|
@ -0,0 +1,35 @@
|
|||
import React from 'react';
|
||||
import { Switch, Route } from 'react-router-dom';
|
||||
import { useAuthorizer } from '@authorizerdev/authorizer-react';
|
||||
import Dashboard from './pages/dashboard';
|
||||
import Login from './pages/login';
|
||||
import ResetPassword from './pages/rest-password';
|
||||
|
||||
export default function Root() {
|
||||
const { token, loading } = useAuthorizer();
|
||||
|
||||
if (loading) {
|
||||
return <h1>Loading...</h1>;
|
||||
}
|
||||
|
||||
if (token) {
|
||||
return (
|
||||
<Switch>
|
||||
<Route path="/app" exact>
|
||||
<Dashboard />
|
||||
</Route>
|
||||
</Switch>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Switch>
|
||||
<Route path="/app" exact>
|
||||
<Login />
|
||||
</Route>
|
||||
<Route path="/app/reset-password">
|
||||
<ResetPassword />
|
||||
</Route>
|
||||
</Switch>
|
||||
);
|
||||
}
|
5
app/src/index.tsx
Normal file
5
app/src/index.tsx
Normal file
|
@ -0,0 +1,5 @@
|
|||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import App from './App';
|
||||
|
||||
ReactDOM.render(<App />, document.getElementById('root'));
|
52
app/src/pages/dashboard.tsx
Normal file
52
app/src/pages/dashboard.tsx
Normal file
|
@ -0,0 +1,52 @@
|
|||
import React from 'react';
|
||||
import { useAuthorizer } from '@authorizerdev/authorizer-react';
|
||||
|
||||
export default function Dashboard() {
|
||||
const [loading, setLoading] = React.useState(false);
|
||||
const { user, setToken, graphQlRef } = useAuthorizer();
|
||||
|
||||
const onLogout = async () => {
|
||||
setLoading(true);
|
||||
await graphQlRef
|
||||
.mutation(
|
||||
`
|
||||
mutation {
|
||||
logout {
|
||||
message
|
||||
}
|
||||
}
|
||||
`
|
||||
)
|
||||
.toPromise();
|
||||
setToken(null);
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1>Hey 👋,</h1>
|
||||
<p>Thank you for joining authorizer demo app.</p>
|
||||
<p>
|
||||
Your email address is{' '}
|
||||
<a href={`mailto:${user?.email}`} style={{ color: '#3B82F6' }}>
|
||||
{user?.email}
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<br />
|
||||
{loading ? (
|
||||
<h3>Processing....</h3>
|
||||
) : (
|
||||
<h3
|
||||
style={{
|
||||
color: '#3B82F6',
|
||||
cursor: 'pointer',
|
||||
}}
|
||||
onClick={onLogout}
|
||||
>
|
||||
Logout
|
||||
</h3>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
10
app/src/pages/login.tsx
Normal file
10
app/src/pages/login.tsx
Normal file
|
@ -0,0 +1,10 @@
|
|||
import React, { Fragment } from 'react';
|
||||
import { Authorizer } from '@authorizerdev/authorizer-react';
|
||||
|
||||
export default function Login() {
|
||||
return (
|
||||
<Fragment>
|
||||
<Authorizer />
|
||||
</Fragment>
|
||||
);
|
||||
}
|
12
app/src/pages/rest-password.tsx
Normal file
12
app/src/pages/rest-password.tsx
Normal file
|
@ -0,0 +1,12 @@
|
|||
import React, { Fragment } from 'react';
|
||||
import { AuthorizerResetPassword } from '@authorizerdev/authorizer-react';
|
||||
|
||||
export default function ResetPassword() {
|
||||
return (
|
||||
<Fragment>
|
||||
<h1 style={{ textAlign: 'center' }}>Reset Password</h1>
|
||||
<br />
|
||||
<AuthorizerResetPassword />
|
||||
</Fragment>
|
||||
);
|
||||
}
|
72
app/tsconfig.json
Normal file
72
app/tsconfig.json
Normal file
|
@ -0,0 +1,72 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
/* Visit https://aka.ms/tsconfig.json to read more about this file */
|
||||
|
||||
/* Basic Options */
|
||||
// "incremental": true, /* Enable incremental compilation */
|
||||
"target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', 'ES2021', or 'ESNEXT'. */
|
||||
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
|
||||
// "lib": ["es2018", "dom"], /* Specify library files to be included in the compilation. */
|
||||
// "allowJs": true, /* Allow javascript files to be compiled. */
|
||||
// "checkJs": true, /* Report errors in .js files. */
|
||||
"jsx": "react", /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */
|
||||
// "declaration": true, /* Generates corresponding '.d.ts' file. */
|
||||
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
|
||||
// "sourceMap": true, /* Generates corresponding '.map' file. */
|
||||
// "outFile": "./", /* Concatenate and emit output to single file. */
|
||||
// "outDir": "./", /* Redirect output structure to the directory. */
|
||||
"rootDir": "src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
||||
// "composite": true, /* Enable project compilation */
|
||||
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
|
||||
// "removeComments": true, /* Do not emit comments to output. */
|
||||
// "noEmit": true, /* Do not emit outputs. */
|
||||
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
|
||||
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
|
||||
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
|
||||
|
||||
/* Strict Type-Checking Options */
|
||||
"strict": true, /* Enable all strict type-checking options. */
|
||||
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
|
||||
// "strictNullChecks": true, /* Enable strict null checks. */
|
||||
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
|
||||
// "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
|
||||
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
|
||||
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
|
||||
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
|
||||
|
||||
/* Additional Checks */
|
||||
// "noUnusedLocals": true, /* Report errors on unused locals. */
|
||||
// "noUnusedParameters": true, /* Report errors on unused parameters. */
|
||||
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
|
||||
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
|
||||
// "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */
|
||||
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an 'override' modifier. */
|
||||
// "noPropertyAccessFromIndexSignature": true, /* Require undeclared properties from index signatures to use element accesses. */
|
||||
|
||||
/* Module Resolution Options */
|
||||
// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
|
||||
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
|
||||
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
|
||||
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
|
||||
// "typeRoots": [], /* List of folders to include type definitions from. */
|
||||
// "types": [], /* Type declaration files to be included in compilation. */
|
||||
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
|
||||
"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
|
||||
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
|
||||
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
||||
|
||||
/* Source Map Options */
|
||||
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
|
||||
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
|
||||
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
|
||||
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
|
||||
|
||||
/* Experimental Options */
|
||||
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
|
||||
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
|
||||
|
||||
/* Advanced Options */
|
||||
"skipLibCheck": true, /* Skip type checking of declaration files. */
|
||||
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
|
||||
}
|
||||
}
|
|
@ -17,4 +17,4 @@ services:
|
|||
depends_on:
|
||||
- db
|
||||
env_file:
|
||||
- server/.env
|
||||
- .env
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
DEFAULT_VERSION=0.1.0-local
|
||||
VERSION := $(or $(VERSION),$(DEFAULT_VERSION))
|
||||
|
||||
cmd:
|
||||
go build -ldflags "-w -X main.Version=$(VERSION)"
|
||||
clean:
|
||||
rm -rf server
|
|
@ -12,8 +12,9 @@ var (
|
|||
SENDER_PASSWORD = ""
|
||||
JWT_TYPE = ""
|
||||
JWT_SECRET = ""
|
||||
FRONTEND_URL = ""
|
||||
AUTHORIZER_DOMAIN = ""
|
||||
ALLOWED_ORIGINS = []string{}
|
||||
ALLOWED_CALLBACK_URLS = []string{}
|
||||
AUTHORIZER_URL = ""
|
||||
PORT = "8080"
|
||||
REDIS_URL = ""
|
||||
IS_PROD = false
|
||||
|
|
|
@ -17,7 +17,7 @@ var Version string
|
|||
func ParseArgs() {
|
||||
dbURL := flag.String("database_url", "", "Database connection string")
|
||||
dbType := flag.String("databse_type", "", "Database type, possible values are postgres,mysql,sqlit")
|
||||
authroizerDomain := flag.String("authorizer_domain", "", "Domain name for authorizer instance, eg: https://xyz.herokuapp.com")
|
||||
authorizerURL := flag.String("AUTHORIZER_URL", "", "URL for authorizer instance, eg: https://xyz.herokuapp.com")
|
||||
flag.Parse()
|
||||
if *dbURL != "" {
|
||||
constants.DATABASE_URL = *dbURL
|
||||
|
@ -27,8 +27,8 @@ func ParseArgs() {
|
|||
constants.DATABASE_TYPE = *dbType
|
||||
}
|
||||
|
||||
if *authroizerDomain != "" {
|
||||
constants.AUTHORIZER_DOMAIN = *authroizerDomain
|
||||
if *authorizerURL != "" {
|
||||
constants.AUTHORIZER_URL = *authorizerURL
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -51,8 +51,7 @@ func InitEnv() {
|
|||
constants.SENDER_PASSWORD = os.Getenv("SENDER_PASSWORD")
|
||||
constants.JWT_SECRET = os.Getenv("JWT_SECRET")
|
||||
constants.JWT_TYPE = os.Getenv("JWT_TYPE")
|
||||
constants.FRONTEND_URL = strings.TrimSuffix(os.Getenv("FRONTEND_URL"), "/")
|
||||
constants.AUTHORIZER_DOMAIN = strings.TrimSuffix(os.Getenv("AUTHORIZER_DOMAIN"), "/")
|
||||
constants.AUTHORIZER_URL = strings.TrimSuffix(os.Getenv("AUTHORIZER_URL"), "/")
|
||||
constants.PORT = os.Getenv("PORT")
|
||||
constants.REDIS_URL = os.Getenv("REDIS_URL")
|
||||
constants.COOKIE_NAME = os.Getenv("COOKIE_NAME")
|
||||
|
@ -84,6 +83,32 @@ func InitEnv() {
|
|||
constants.IS_PROD = false
|
||||
}
|
||||
|
||||
allowedOriginsSplit := strings.Split(os.Getenv("ALLOWED_ORIGINS"), ",")
|
||||
allowedOrigins := []string{}
|
||||
for _, val := range allowedOriginsSplit {
|
||||
trimVal := strings.TrimSpace(val)
|
||||
if trimVal != "" {
|
||||
allowedOrigins = append(allowedOrigins, trimVal)
|
||||
}
|
||||
}
|
||||
if len(allowedOrigins) == 0 {
|
||||
allowedOrigins = []string{"*"}
|
||||
}
|
||||
constants.ALLOWED_ORIGINS = allowedOrigins
|
||||
|
||||
allowedCallbackSplit := strings.Split(os.Getenv("ALLOWED_CALLBACK_URLS"), ",")
|
||||
allowedCallbacks := []string{}
|
||||
for _, val := range allowedCallbackSplit {
|
||||
trimVal := strings.TrimSpace(val)
|
||||
if trimVal != "" {
|
||||
allowedCallbacks = append(allowedCallbacks, trimVal)
|
||||
}
|
||||
}
|
||||
if len(allowedCallbackSplit) == 0 {
|
||||
allowedCallbackSplit = []string{"*"}
|
||||
}
|
||||
constants.ALLOWED_CALLBACK_URLS = allowedCallbackSplit
|
||||
|
||||
ParseArgs()
|
||||
if constants.DATABASE_URL == "" {
|
||||
panic("Database url is required")
|
||||
|
@ -101,10 +126,6 @@ func InitEnv() {
|
|||
constants.COOKIE_NAME = "authorizer"
|
||||
}
|
||||
|
||||
if constants.AUTHORIZER_DOMAIN == "" {
|
||||
constants.AUTHORIZER_DOMAIN = "http://localhost:8080"
|
||||
}
|
||||
|
||||
if constants.DISABLE_BASIC_AUTHENTICATION == "" {
|
||||
constants.DISABLE_BASIC_AUTHENTICATION = "false"
|
||||
}
|
||||
|
|
|
@ -5,19 +5,24 @@ go 1.16
|
|||
require (
|
||||
github.com/99designs/gqlgen v0.13.0
|
||||
github.com/gin-gonic/gin v1.7.2
|
||||
github.com/go-playground/validator/v10 v10.8.0 // indirect
|
||||
github.com/go-redis/redis/v8 v8.11.0
|
||||
github.com/golang-jwt/jwt v3.2.1+incompatible
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/jackc/pgproto3/v2 v2.1.0 // indirect
|
||||
github.com/joho/godotenv v1.3.0
|
||||
github.com/json-iterator/go v1.1.11 // indirect
|
||||
github.com/mattn/go-isatty v0.0.13 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.14.7 // indirect
|
||||
github.com/ugorji/go v1.2.6 // indirect
|
||||
github.com/vektah/gqlparser/v2 v2.1.0
|
||||
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e
|
||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97
|
||||
golang.org/x/net v0.0.0-20210614182718-04defd469f4e // indirect
|
||||
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/protobuf v1.27.1 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gorm.io/driver/mysql v1.1.1
|
||||
gorm.io/driver/postgres v1.1.0
|
||||
gorm.io/driver/sqlite v1.1.4
|
||||
|
|
|
@ -68,7 +68,6 @@ github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+Ce
|
|||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
|
||||
github.com/cenkalti/backoff v2.1.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
||||
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=
|
||||
|
@ -88,19 +87,11 @@ github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7
|
|||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dghubble/go-twitter v0.0.0-20190719072343-39e5462e111f/go.mod h1:xfg4uS5LEzOj8PgZV7SQYRHbG7jPUnelEiaAVJxmhJE=
|
||||
github.com/dghubble/gologin v2.1.0+incompatible h1:LAk9a91axNP72AGTNp7afVigkdhakN7IyDGcceQ+R6g=
|
||||
github.com/dghubble/gologin v2.1.0+incompatible/go.mod h1:+EjjX5AiOREcyqxhz0c6I8OsL+6F9/38WD1CDcClx+Y=
|
||||
github.com/dghubble/gologin/v2 v2.3.0 h1:SMHahscgKmgrv4X+OAwFCJCuJ6mbLxOqB+FAVU+tOSA=
|
||||
github.com/dghubble/gologin/v2 v2.3.0/go.mod h1:qGAUHuIYV0WP3kwoPjLhG+YIlGqy8O13YjItosCBKdo=
|
||||
github.com/dghubble/oauth1 v0.6.0/go.mod h1:8pFdfPkv/jr8mkChVbNVuJ0suiHe278BtWI4Tk1ujxk=
|
||||
github.com/dghubble/sling v1.3.0/go.mod h1:XXShWaBWKzNLhu2OxikSNFrlsvowtz4kyRuXUG7oQKY=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||
|
@ -143,8 +134,9 @@ github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8c
|
|||
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
|
||||
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
|
||||
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
|
||||
github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE=
|
||||
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
|
||||
github.com/go-playground/validator/v10 v10.8.0 h1:1kAa0fCrnpv+QYdkdcRzrRM7AyYs5o8+jZdJCz9xj6k=
|
||||
github.com/go-playground/validator/v10 v10.8.0/go.mod h1:9JhgTzTaE31GZDpH/HSvHiRJrJ3iKAgqqH0Bl/Ocjdk=
|
||||
github.com/go-redis/redis/v8 v8.11.0 h1:O1Td0mQ8UFChQ3N9zFQqo6kTU2cJ+/it88gDB+zg0wo=
|
||||
github.com/go-redis/redis/v8 v8.11.0/go.mod h1:DLomh7y2e3ggQXQLd1YgmvIfecPJoFl7WU5SOQ/r06M=
|
||||
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
|
@ -201,8 +193,6 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
|||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
|
@ -322,8 +312,9 @@ github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22
|
|||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
|
||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ=
|
||||
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
|
@ -339,8 +330,9 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
|||
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
|
||||
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
||||
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
|
||||
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
|
||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
|
@ -362,8 +354,9 @@ github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd
|
|||
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.13 h1:qdl+GuBjcsKKDco5BsxPJlId98mSWNKqYA+Co0SC1yA=
|
||||
github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-sqlite3 v1.14.5/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI=
|
||||
github.com/mattn/go-sqlite3 v1.14.7 h1:fxWBnXkxfM6sRiuH3bqJ4CfzZojMOLVc0UTsTglEghA=
|
||||
|
@ -453,7 +446,6 @@ github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
|
|||
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
|
||||
github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
|
||||
github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc=
|
||||
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
|
||||
|
@ -465,7 +457,6 @@ github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9Nz
|
|||
github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc h1:jUIKcSPO9MoMJBbEoyE/RJoE8vz7Mb8AjvifMMwSyvY=
|
||||
github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||
github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/shurcooL/vfsgen v0.0.0-20180121065927-ffb13db8def0/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
|
@ -487,17 +478,18 @@ github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
|
|||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
|
||||
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
||||
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
|
||||
github.com/ugorji/go v1.2.6 h1:tGiWC9HENWE2tqYycIqFTNorMmFRVhNwCpDOpWqnk8E=
|
||||
github.com/ugorji/go v1.2.6/go.mod h1:anCg0y61KIhDlPZmnH+so+RQbysYVyDko0IMgJv0Nn0=
|
||||
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
||||
github.com/ugorji/go/codec v1.2.6 h1:7kbGefxLoDBuYXOms4yD7223OpNMMPNPZxXk5TvFcyQ=
|
||||
github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw=
|
||||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||
github.com/urfave/cli v1.22.1 h1:+mkCCcOFKPnCmVYVcURKps1Xe+3zP90gSYGNfRkjoIY=
|
||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
github.com/urfave/cli/v2 v2.1.1 h1:Qt8FeAtxE/vfdrLmR3rxR6JRE0RoVmbXu8+6kZtYU4k=
|
||||
github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ=
|
||||
github.com/vektah/dataloaden v0.2.1-0.20190515034641-a19b9a6e7c9e/go.mod h1:/HUdMve7rvxZma+2ZELQeNh88+003LL7Pf/CZ089j8U=
|
||||
github.com/vektah/gqlparser/v2 v2.1.0 h1:uiKJ+T5HMGGQM2kRKQ8Pxw8+Zq9qhhZhz/lieYvCMns=
|
||||
|
@ -541,8 +533,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
|
|||
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e h1:gsTQYXdTw2Gq7RBsWvlQ91b+aEQ6bXFUngBGuR8sPpI=
|
||||
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 h1:/UOmuWzQfxxo9UtlXMwuQU8CMgg1eZXqTRwkSQJWKOI=
|
||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
|
@ -572,7 +564,6 @@ golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
|||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
|
@ -676,8 +667,9 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
|
@ -741,7 +733,6 @@ golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roY
|
|||
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e h1:4nW4NLDYnU28ojHaHO8OVxFHk/aQ33U01a9cjED+pzE=
|
||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
@ -856,8 +847,11 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gorm.io/driver/mysql v1.1.1 h1:yr1bpyqiwuSPJ4aGGUX9nu46RHXlF8RASQVb1QQNcvo=
|
||||
gorm.io/driver/mysql v1.1.1/go.mod h1:KdrTanmfLPPyAOeYGyG+UpDys7/7eeWT1zCq+oekYnU=
|
||||
gorm.io/driver/postgres v1.1.0 h1:afBljg7PtJ5lA6YUWluV2+xovIPhS+YiInuL3kUjrbk=
|
||||
|
|
87
server/handlers/app.go
Normal file
87
server/handlers/app.go
Normal file
|
@ -0,0 +1,87 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type State struct {
|
||||
AuthorizerURL string `json:"authorizerURL"`
|
||||
RedirectURL string `json:"redirectURL"`
|
||||
}
|
||||
|
||||
func AppHandler() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
host := "http://" + c.Request.Host
|
||||
state := c.Query("state")
|
||||
var stateObj State
|
||||
|
||||
if state == "" {
|
||||
cookie, err := utils.GetAuthToken(c)
|
||||
log.Println(`cookie`, cookie)
|
||||
if err != nil {
|
||||
c.JSON(400, gin.H{"error": "invalid state"})
|
||||
return
|
||||
}
|
||||
|
||||
stateObj.AuthorizerURL = host
|
||||
stateObj.RedirectURL = host + "/app"
|
||||
|
||||
} else {
|
||||
decodedState, err := base64.StdEncoding.DecodeString(state)
|
||||
if err != nil {
|
||||
c.JSON(400, gin.H{"error": "[unable to decode state] invalid state"})
|
||||
return
|
||||
}
|
||||
|
||||
err = json.Unmarshal(decodedState, &stateObj)
|
||||
if err != nil {
|
||||
c.JSON(400, gin.H{"error": "[unable to parse state] invalid state"})
|
||||
return
|
||||
}
|
||||
|
||||
// validate redirect url with allowed origins
|
||||
if !utils.IsValidRedirectURL(stateObj.RedirectURL) {
|
||||
c.JSON(400, gin.H{"error": "invalid redirect url"})
|
||||
return
|
||||
}
|
||||
|
||||
if stateObj.AuthorizerURL == "" {
|
||||
c.JSON(400, gin.H{"error": "invalid authorizer url"})
|
||||
return
|
||||
}
|
||||
|
||||
// validate host and domain of authorizer url
|
||||
if utils.GetDomainName(stateObj.AuthorizerURL) != utils.GetDomainName(host) {
|
||||
c.JSON(400, gin.H{"error": "invalid host url"})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
log.Println(gin.H{
|
||||
"data": map[string]string{
|
||||
"authorizerURL": "http://" + stateObj.AuthorizerURL,
|
||||
"redirectURL": stateObj.RedirectURL,
|
||||
},
|
||||
})
|
||||
|
||||
// debug the request state
|
||||
if pusher := c.Writer.Pusher(); pusher != nil {
|
||||
// use pusher.Push() to do server push
|
||||
if err := pusher.Push("/app/build/bundle.js", nil); err != nil {
|
||||
log.Printf("Failed to push: %v", err)
|
||||
}
|
||||
}
|
||||
c.HTML(http.StatusOK, "app.tmpl", gin.H{
|
||||
"data": map[string]string{
|
||||
"authorizerURL": stateObj.AuthorizerURL,
|
||||
"redirectURL": stateObj.RedirectURL,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
|
@ -15,8 +15,8 @@ func GraphqlHandler() gin.HandlerFunc {
|
|||
h := handler.NewDefaultServer(generated.NewExecutableSchema(generated.Config{Resolvers: &graph.Resolver{}}))
|
||||
|
||||
return func(c *gin.Context) {
|
||||
if constants.AUTHORIZER_DOMAIN == "" {
|
||||
constants.AUTHORIZER_DOMAIN = "https://" + c.Request.Host
|
||||
if constants.AUTHORIZER_URL == "" {
|
||||
constants.AUTHORIZER_URL = "https://" + c.Request.Host
|
||||
}
|
||||
h.ServeHTTP(c.Writer, c.Request)
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
@ -18,12 +19,7 @@ import (
|
|||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
func processGoogleUserInfo(state string, code string, c *gin.Context) error {
|
||||
sessionState := session.GetToken(state)
|
||||
if sessionState == "" {
|
||||
return fmt.Errorf("invalid oauth state")
|
||||
}
|
||||
session.DeleteToken(sessionState)
|
||||
func processGoogleUserInfo(code string, c *gin.Context) error {
|
||||
token, err := oauth.OAuthProvider.GoogleConfig.Exchange(oauth2.NoContext, code)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid google exchange code: %s", err.Error())
|
||||
|
@ -82,12 +78,7 @@ func processGoogleUserInfo(state string, code string, c *gin.Context) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func processGithubUserInfo(state string, code string, c *gin.Context) error {
|
||||
sessionState := session.GetToken(state)
|
||||
if sessionState == "" {
|
||||
return fmt.Errorf("invalid oauth state")
|
||||
}
|
||||
session.DeleteToken(sessionState)
|
||||
func processGithubUserInfo(code string, c *gin.Context) error {
|
||||
token, err := oauth.OAuthProvider.GithubConfig.Exchange(oauth2.NoContext, code)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid google exchange code: %s", err.Error())
|
||||
|
@ -165,21 +156,38 @@ func processGithubUserInfo(state string, code string, c *gin.Context) error {
|
|||
|
||||
func OAuthCallbackHandler() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
log.Println("url:", c.Request.URL)
|
||||
provider := c.Param("oauth_provider")
|
||||
state := c.Request.FormValue("state")
|
||||
log.Println("session state", state)
|
||||
sessionState := session.GetToken(state)
|
||||
if sessionState == "" {
|
||||
c.JSON(400, gin.H{"error": "invalid oauth state"})
|
||||
}
|
||||
session.DeleteToken(sessionState)
|
||||
sessionSplit := strings.Split(state, "___")
|
||||
log.Println(sessionSplit)
|
||||
// TODO validate redirect url
|
||||
if len(sessionSplit) != 2 {
|
||||
c.JSON(400, gin.H{"error": "invalid redirect url"})
|
||||
return
|
||||
}
|
||||
|
||||
var err error
|
||||
code := c.Request.FormValue("code")
|
||||
switch provider {
|
||||
case enum.Google.String():
|
||||
err = processGoogleUserInfo(c.Request.FormValue("state"), c.Request.FormValue("code"), c)
|
||||
err = processGoogleUserInfo(code, c)
|
||||
case enum.Github.String():
|
||||
err = processGithubUserInfo(c.Request.FormValue("state"), c.Request.FormValue("code"), c)
|
||||
err = processGithubUserInfo(code, c)
|
||||
default:
|
||||
err = fmt.Errorf(`invalid oauth provider`)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
c.Redirect(http.StatusTemporaryRedirect, constants.FRONTEND_URL+"?error="+err.Error())
|
||||
c.JSON(400, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
c.Redirect(http.StatusTemporaryRedirect, constants.FRONTEND_URL)
|
||||
c.Redirect(http.StatusTemporaryRedirect, sessionSplit[1])
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,11 +10,22 @@ import (
|
|||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
func OAuthLoginHandler() gin.HandlerFunc {
|
||||
uuid := uuid.New()
|
||||
oauthStateString := uuid.String()
|
||||
// set host in the oauth state that is useful for redirecting
|
||||
|
||||
func OAuthLoginHandler() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
// TODO validate redirect URL
|
||||
redirectURL := c.Query("redirectURL")
|
||||
|
||||
if redirectURL == "" {
|
||||
c.JSON(400, gin.H{
|
||||
"error": "invalid redirect url",
|
||||
})
|
||||
return
|
||||
}
|
||||
uuid := uuid.New()
|
||||
oauthStateString := uuid.String() + "___" + redirectURL
|
||||
|
||||
provider := c.Param("oauth_provider")
|
||||
|
||||
switch provider {
|
||||
|
|
|
@ -5,7 +5,6 @@ import (
|
|||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/db"
|
||||
"github.com/authorizerdev/authorizer/server/enum"
|
||||
"github.com/authorizerdev/authorizer/server/session"
|
||||
|
@ -63,6 +62,6 @@ func VerifyEmailHandler() gin.HandlerFunc {
|
|||
|
||||
session.SetToken(userIdStr, refreshToken)
|
||||
utils.SetCookie(c, accessToken)
|
||||
c.Redirect(http.StatusTemporaryRedirect, constants.FRONTEND_URL)
|
||||
c.Redirect(http.StatusTemporaryRedirect, claim.Host)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,8 @@ func GinContextToContextMiddleware() gin.HandlerFunc {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO use allowed origins for cors origin
|
||||
// TODO throw error if url is not allowed
|
||||
func CORSMiddleware() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
origin := c.Request.Header.Get("Origin")
|
||||
|
@ -44,10 +46,17 @@ func main() {
|
|||
r := gin.Default()
|
||||
r.Use(GinContextToContextMiddleware())
|
||||
r.Use(CORSMiddleware())
|
||||
|
||||
r.GET("/", handlers.PlaygroundHandler())
|
||||
r.POST("/graphql", handlers.GraphqlHandler())
|
||||
r.GET("/verify_email", handlers.VerifyEmailHandler())
|
||||
r.GET("/login/:oauth_provider", handlers.OAuthLoginHandler())
|
||||
r.GET("/callback/:oauth_provider", handlers.OAuthCallbackHandler())
|
||||
r.GET("/oauth_login/:oauth_provider", handlers.OAuthLoginHandler())
|
||||
r.GET("/oauth_callback/:oauth_provider", handlers.OAuthCallbackHandler())
|
||||
|
||||
// login wall app related routes
|
||||
r.Static("/app/build", "app/build")
|
||||
r.LoadHTMLGlob("templates/*")
|
||||
r.GET("/app", handlers.AppHandler())
|
||||
|
||||
r.Run()
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ func InitOAuth() {
|
|||
OAuthProvider.GoogleConfig = &oauth2.Config{
|
||||
ClientID: constants.GOOGLE_CLIENT_ID,
|
||||
ClientSecret: constants.GOOGLE_CLIENT_SECRET,
|
||||
RedirectURL: constants.AUTHORIZER_DOMAIN + "/callback/google",
|
||||
RedirectURL: constants.AUTHORIZER_URL + "/oauth_callback/google",
|
||||
Endpoint: googleOAuth2.Endpoint,
|
||||
Scopes: []string{"https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/userinfo.profile"},
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ func InitOAuth() {
|
|||
OAuthProvider.GithubConfig = &oauth2.Config{
|
||||
ClientID: constants.GITHUB_CLIENT_ID,
|
||||
ClientSecret: constants.GITHUB_CLIENT_SECRET,
|
||||
RedirectURL: constants.AUTHORIZER_DOMAIN + "/callback/github",
|
||||
RedirectURL: constants.AUTHORIZER_URL + "/oauth_callback/github",
|
||||
Endpoint: githubOAuth2.Endpoint,
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ func InitOAuth() {
|
|||
// OAuthProvider.FacebookConfig = &oauth2.Config{
|
||||
// ClientID: constants.FACEBOOK_CLIENT_ID,
|
||||
// ClientSecret: constants.FACEBOOK_CLIENT_SECRET,
|
||||
// RedirectURL: "/callback/facebook/",
|
||||
// RedirectURL: "/oauth_callback/facebook/",
|
||||
// Endpoint: facebookOAuth2.Endpoint,
|
||||
// }
|
||||
// }
|
||||
|
|
|
@ -15,23 +15,27 @@ import (
|
|||
)
|
||||
|
||||
func ForgotPassword(ctx context.Context, params model.ForgotPasswordInput) (*model.Response, error) {
|
||||
gc, err := utils.GinContextFromContext(ctx)
|
||||
var res *model.Response
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
if constants.DISABLE_BASIC_AUTHENTICATION == "true" {
|
||||
return res, fmt.Errorf(`basic authentication is disabled for this instance`)
|
||||
}
|
||||
|
||||
host := gc.Request.Host
|
||||
params.Email = strings.ToLower(params.Email)
|
||||
|
||||
if !utils.IsValidEmail(params.Email) {
|
||||
return res, fmt.Errorf("invalid email")
|
||||
}
|
||||
|
||||
_, err := db.Mgr.GetUserByEmail(params.Email)
|
||||
_, err = db.Mgr.GetUserByEmail(params.Email)
|
||||
if err != nil {
|
||||
return res, fmt.Errorf(`user with this email not found`)
|
||||
}
|
||||
|
||||
token, err := utils.CreateVerificationToken(params.Email, enum.ForgotPassword.String())
|
||||
token, err := utils.CreateVerificationToken(params.Email, enum.ForgotPassword.String(), host)
|
||||
if err != nil {
|
||||
log.Println(`Error generating token`, err)
|
||||
}
|
||||
|
@ -44,7 +48,7 @@ func ForgotPassword(ctx context.Context, params model.ForgotPasswordInput) (*mod
|
|||
|
||||
// exec it as go routin so that we can reduce the api latency
|
||||
go func() {
|
||||
utils.SendForgotPasswordMail(params.Email, token)
|
||||
utils.SendForgotPasswordMail(params.Email, token, host)
|
||||
}()
|
||||
|
||||
res = &model.Response{
|
||||
|
|
|
@ -13,19 +13,25 @@ import (
|
|||
)
|
||||
|
||||
func ResendVerifyEmail(ctx context.Context, params model.ResendVerifyEmailInput) (*model.Response, error) {
|
||||
gc, err := utils.GinContextFromContext(ctx)
|
||||
var res *model.Response
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
params.Email = strings.ToLower(params.Email)
|
||||
|
||||
if !utils.IsValidEmail(params.Email) {
|
||||
return res, fmt.Errorf("invalid email")
|
||||
}
|
||||
|
||||
host := gc.Request.Host
|
||||
|
||||
verificationRequest, err := db.Mgr.GetVerificationByEmail(params.Email)
|
||||
if err != nil {
|
||||
return res, fmt.Errorf(`verification request not found`)
|
||||
}
|
||||
|
||||
token, err := utils.CreateVerificationToken(params.Email, verificationRequest.Identifier)
|
||||
token, err := utils.CreateVerificationToken(params.Email, verificationRequest.Identifier, host)
|
||||
if err != nil {
|
||||
log.Println(`Error generating token`, err)
|
||||
}
|
||||
|
|
|
@ -84,7 +84,7 @@ func Signup(ctx context.Context, params model.SignUpInput) (*model.AuthResponse,
|
|||
if constants.DISABLE_EMAIL_VERICATION != "true" {
|
||||
// insert verification request
|
||||
verificationType := enum.BasicAuthSignup.String()
|
||||
token, err := utils.CreateVerificationToken(params.Email, verificationType)
|
||||
token, err := utils.CreateVerificationToken(params.Email, verificationType, gc.Request.Host)
|
||||
if err != nil {
|
||||
log.Println(`Error generating token`, err)
|
||||
}
|
||||
|
|
|
@ -105,7 +105,7 @@ func UpdateProfile(ctx context.Context, params model.UpdateProfileInput) (*model
|
|||
hasEmailChanged = true
|
||||
// insert verification request
|
||||
verificationType := enum.UpdateEmail.String()
|
||||
token, err := utils.CreateVerificationToken(newEmail, verificationType)
|
||||
token, err := utils.CreateVerificationToken(newEmail, verificationType, gc.Request.Host)
|
||||
if err != nil {
|
||||
log.Println(`Error generating token`, err)
|
||||
}
|
||||
|
@ -124,6 +124,10 @@ func UpdateProfile(ctx context.Context, params model.UpdateProfileInput) (*model
|
|||
}
|
||||
|
||||
_, err = db.Mgr.UpdateUser(user)
|
||||
if err != nil {
|
||||
log.Println("Error updating user:", err)
|
||||
return res, err
|
||||
}
|
||||
message := `Profile details updated successfully.`
|
||||
if hasEmailChanged {
|
||||
message += `For the email change we have sent new verification email, please verify and continue`
|
||||
|
|
|
@ -12,8 +12,8 @@ func SetCookie(gc *gin.Context, token string) {
|
|||
secure := true
|
||||
httpOnly := true
|
||||
|
||||
host := GetDomainName(gc.Request.Host)
|
||||
log.Println("=> host", host)
|
||||
host := GetHostName(gc.Request.Host)
|
||||
log.Println("=> cookie host", host)
|
||||
gc.SetSameSite(http.SameSiteNoneMode)
|
||||
gc.SetCookie(constants.COOKIE_NAME, token, 3600, "/", host, secure, httpOnly)
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ func DeleteCookie(gc *gin.Context) {
|
|||
secure = false
|
||||
}
|
||||
|
||||
host := GetDomainName(gc.Request.Host)
|
||||
host := GetHostName(gc.Request.Host)
|
||||
gc.SetSameSite(http.SameSiteNoneMode)
|
||||
gc.SetCookie(constants.COOKIE_NAME, "", -1, "/", host, secure, httpOnly)
|
||||
}
|
||||
|
|
|
@ -26,14 +26,14 @@ func SendVerificationMail(toEmail, token string) error {
|
|||
<a href="%s">Click here to verify</a>
|
||||
</body>
|
||||
</html>
|
||||
`, constants.AUTHORIZER_DOMAIN+"/verify_email"+"?token="+token)
|
||||
`, constants.AUTHORIZER_URL+"/verify_email"+"?token="+token)
|
||||
bodyMessage := sender.WriteHTMLEmail(Receiver, Subject, message)
|
||||
|
||||
return sender.SendMail(Receiver, Subject, bodyMessage)
|
||||
}
|
||||
|
||||
// SendForgotPasswordMail to send verification email
|
||||
func SendForgotPasswordMail(toEmail, token string) error {
|
||||
func SendForgotPasswordMail(toEmail, token, host string) error {
|
||||
sender := email.NewSender()
|
||||
|
||||
// The receiver needs to be in slice as the receive supports multiple receiver
|
||||
|
@ -51,7 +51,7 @@ func SendForgotPasswordMail(toEmail, token string) error {
|
|||
<a href="%s">Reset Password</a>
|
||||
</body>
|
||||
</html>
|
||||
`, constants.FRONTEND_URL+"/"+constants.FORGOT_PASSWORD_URI+"?token="+token)
|
||||
`, host+"/"+constants.FORGOT_PASSWORD_URI+"?token="+token)
|
||||
bodyMessage := sender.WriteHTMLEmail(Receiver, Subject, message)
|
||||
|
||||
return sender.SendMail(Receiver, Subject, bodyMessage)
|
||||
|
|
|
@ -2,11 +2,24 @@ package utils
|
|||
|
||||
import (
|
||||
"net/url"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// function to get hostname
|
||||
func GetHostName(auth_url string) string {
|
||||
u, err := url.Parse(auth_url)
|
||||
if err != nil {
|
||||
return `localhost`
|
||||
}
|
||||
|
||||
host := u.Hostname()
|
||||
|
||||
return host
|
||||
}
|
||||
|
||||
// function to get domain name
|
||||
func GetDomainName(auth_url string) string {
|
||||
u, err := url.Parse("//" + auth_url)
|
||||
u, err := url.Parse(auth_url)
|
||||
if err != nil {
|
||||
return `localhost`
|
||||
}
|
||||
|
@ -14,24 +27,24 @@ func GetDomainName(auth_url string) string {
|
|||
host := u.Hostname()
|
||||
|
||||
// code to get root domain in case of sub-domains
|
||||
// hostParts := strings.Split(host, ".")
|
||||
// hostPartsLen := len(hostParts)
|
||||
hostParts := strings.Split(host, ".")
|
||||
hostPartsLen := len(hostParts)
|
||||
|
||||
// if hostPartsLen == 1 {
|
||||
// return host
|
||||
// }
|
||||
if hostPartsLen == 1 {
|
||||
return host
|
||||
}
|
||||
|
||||
// if hostPartsLen == 2 {
|
||||
// if hostParts[0] == "www" {
|
||||
// return hostParts[1]
|
||||
// } else {
|
||||
// return host
|
||||
// }
|
||||
// }
|
||||
if hostPartsLen == 2 {
|
||||
if hostParts[0] == "www" {
|
||||
return hostParts[1]
|
||||
} else {
|
||||
return host
|
||||
}
|
||||
}
|
||||
|
||||
// if hostPartsLen > 2 {
|
||||
// return strings.Join(hostParts[hostPartsLen-2:], ".")
|
||||
// }
|
||||
if hostPartsLen > 2 {
|
||||
return strings.Join(hostParts[hostPartsLen-2:], ".")
|
||||
}
|
||||
|
||||
return host
|
||||
}
|
||||
|
|
|
@ -1,8 +1,31 @@
|
|||
package utils
|
||||
|
||||
import "net/mail"
|
||||
import (
|
||||
"net/mail"
|
||||
"strings"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
)
|
||||
|
||||
func IsValidEmail(email string) bool {
|
||||
_, err := mail.ParseAddress(email)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
func IsValidRedirectURL(url string) bool {
|
||||
if len(constants.ALLOWED_ORIGINS) == 1 && constants.ALLOWED_ORIGINS[0] == "*" {
|
||||
return true
|
||||
}
|
||||
|
||||
hasValidURL := false
|
||||
urlDomain := GetDomainName(url)
|
||||
|
||||
for _, val := range constants.ALLOWED_ORIGINS {
|
||||
if strings.Contains(val, urlDomain) {
|
||||
hasValidURL = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return hasValidURL
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
|
||||
type UserInfo struct {
|
||||
Email string `json:"email"`
|
||||
Host string `json:"host"`
|
||||
}
|
||||
|
||||
type CustomClaim struct {
|
||||
|
@ -18,7 +19,7 @@ type CustomClaim struct {
|
|||
}
|
||||
|
||||
// TODO convert tokenType to enum
|
||||
func CreateVerificationToken(email string, tokenType string) (string, error) {
|
||||
func CreateVerificationToken(email string, tokenType string, host string) (string, error) {
|
||||
t := jwt.New(jwt.GetSigningMethod(constants.JWT_TYPE))
|
||||
|
||||
t.Claims = &CustomClaim{
|
||||
|
@ -27,7 +28,7 @@ func CreateVerificationToken(email string, tokenType string) (string, error) {
|
|||
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
|
||||
},
|
||||
tokenType,
|
||||
UserInfo{Email: email},
|
||||
UserInfo{Email: email, Host: host},
|
||||
}
|
||||
|
||||
return t.SignedString([]byte(constants.JWT_SECRET))
|
||||
|
|
17
templates/app.tmpl
Normal file
17
templates/app.tmpl
Normal file
|
@ -0,0 +1,17 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Document</title>
|
||||
<link rel="stylesheet" href="/app/build/bundle.css">
|
||||
<script>
|
||||
window.__authorizer__ = {{.data}}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script src="/app/build/bundle.js"></script>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user