From ac538f35ab821cee9a27f2e27781ba2e753f3258 Mon Sep 17 00:00:00 2001 From: thearavind Date: Tue, 7 May 2019 01:15:38 +0530 Subject: [PATCH 1/2] added docker compose and removed redux --- .gitignore | 4 ++- .vscode/settings.json | 3 -- Dockerfile | 2 +- docker-compose.yml | 8 ++++++ go.sum | 4 +++ main.go | 18 ++++++++---- package.json | 3 -- src/App.tsx | 15 ++++------ src/Login.tsx | 2 +- src/Redirect.tsx | 38 +++++++++++------------- src/index.tsx | 10 +------ src/reducer.ts | 26 ----------------- src/store.ts | 22 -------------- tokenHandler.go | 67 +++++++++++++++++++++++++++++++++++++++++++ 14 files changed, 121 insertions(+), 101 deletions(-) delete mode 100644 .vscode/settings.json create mode 100644 docker-compose.yml delete mode 100644 src/reducer.ts delete mode 100644 src/store.ts create mode 100644 tokenHandler.go diff --git a/.gitignore b/.gitignore index bf68b1e..505428d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ node_modules/ -.env.development +.env +build/ +.vscode/ diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index ed94f44..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "git.ignoreLimitWarning": true -} \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 4b7bf7c..3b3c467 100644 --- a/Dockerfile +++ b/Dockerfile @@ -16,7 +16,7 @@ WORKDIR /server COPY --from=react-build /app/build build/ -COPY main.go go.mod go.sum ./ +COPY main.go tokenHandler.go go.mod go.sum ./ RUN go mod download diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..8b77992 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,8 @@ +version: '3' +services: + web: + build: . + ports: + - "3000:3000" + env_file: + - ./.env diff --git a/go.sum b/go.sum index 19f7964..b18112e 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,4 @@ +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/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4= github.com/gin-contrib/sse v0.0.0-20170109093832-22d885f9ecc7 h1:AzN37oI0cOS+cougNAV9szl6CVoj2RYwzS3DpUQNtlY= @@ -13,10 +14,13 @@ github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/ugorji/go/codec v0.0.0-20181209151446-772ced7fd4c2 h1:EICbibRW4JNKMcY+LsWmuwob+CRS1BmdRdjphAm9mH4= github.com/ugorji/go/codec v0.0.0-20181209151446-772ced7fd4c2/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3 h1:eH6Eip3UpmR+yM/qI9Ijluzb1bNv/cAU/n+6l8tRSis= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20181221143128-b4a75ba826a6/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= diff --git a/main.go b/main.go index e518f07..79b4552 100644 --- a/main.go +++ b/main.go @@ -1,17 +1,25 @@ package main import ( + "fmt" + "os" + "github.com/gin-contrib/static" "github.com/gin-gonic/gin" ) +func noRouteHandler(c *gin.Context) { + c.File("./build/index.html") +} + func main() { + fmt.Printf("Client id -> %s", os.Getenv("CLIENT_ID")) r := gin.Default() - r.Use(static.Serve("/", static.LocalFile("build/", false))) - r.GET("/ping", func(c *gin.Context) { - c.String(200, "test") - }) + r.Use(static.Serve("/", static.LocalFile("./build", true))) + api := r.Group("/api") + api.POST("/generate_token", tokenHandler) + r.NoRoute(noRouteHandler) - r.Run(":8080") + r.Run(":3000") } diff --git a/package.json b/package.json index de4002f..2ec4ad2 100644 --- a/package.json +++ b/package.json @@ -9,14 +9,11 @@ "@types/react-dom": "16.8.3", "@types/react-router": "^4.4.5", "@types/react-router-dom": "^4.3.2", - "@types/redux": "^3.6.0", "react": "^16.8.6", "react-dom": "^16.8.6", "react-router": "^5.0.0", "react-router-dom": "^5.0.0", "react-scripts": "2.1.8", - "redux": "^4.0.1", - "redux-react-hook": "^3.3.1", "typescript": "3.4.2" }, "scripts": { diff --git a/src/App.tsx b/src/App.tsx index 210c91e..bcbd234 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,21 +1,18 @@ import React, { useState } from 'react'; import { BrowserRouter as Router, Route, Link } from "react-router-dom"; -import { StoreContext } from 'redux-react-hook'; import Login from './Login' import Home from './Home' import Redirect from './Redirect' -import { makeStore } from './store'; const App = () => { - const store = makeStore(); return ( - - + +
- - - - + + +
+
); } diff --git a/src/Login.tsx b/src/Login.tsx index 5d4720c..e3fe046 100644 --- a/src/Login.tsx +++ b/src/Login.tsx @@ -7,7 +7,7 @@ const Login = () => { const openPopup = () => { const url = 'https://www.reddit.com/api/v1/authorize' + - `?client_id=CLIENT_ID` + + `?client_id=YdNu-wlTwwHI6A` + `&response_type=code` + `&state=${new Date().valueOf().toString()}` + `&redirect_uri=http://localhost:3000/login-success` + diff --git a/src/Redirect.tsx b/src/Redirect.tsx index 0719cf1..48d73dd 100644 --- a/src/Redirect.tsx +++ b/src/Redirect.tsx @@ -5,27 +5,23 @@ const LoginSuccess = (props: any) => { let defaultValue: boolean | undefined const [isAuthenticated, setIsAuthenticated] = useState(defaultValue); useEffect(() => { - let params = new URLSearchParams(props.location.search) - const authToken = params.get('code') - fetch(`https://www.reddit.com/api/v1/access_token?grant_type=authorization_code&code=${authToken}&redirect_uri=http://localhost:3000/login-success`, { - method: 'POST', - // mode: "no-cors", - // body: `grant_type=authorization_code&code=${authToken}&redirect_uri=http://localhost:3000/login-success`, - headers: { - Authorization: `Basic ${btoa('CLIENT_ID:CLIENT_SECRET')}` - } - }) - .then(res => res.json()) - .then((response) => { - setIsAuthenticated(true) - document.cookie = `accessToken=${response.access_token};` - document.cookie = `refreshToken=${response.refresh_token};` - document.cookie = `expires=${new Date(new Date().getTime() + (10000 * 60 * 60 * 7 * 24))};` - document.cookie = `doamin=localhost;` - }) - .catch(() => { - setIsAuthenticated(false) - }) + // let params = new URLSearchParams(props.location.search) + // const authToken = params.get('code') + // fetch(`/generate_token`, { + // method: 'POST', + // body: JSON.stringify({ code: authToken }) + // }) + // .then(res => res.json()) + // .then((response) => { + // setIsAuthenticated(true) + // document.cookie = `accessToken=${response.access_token};` + // document.cookie = `refreshToken=${response.refresh_token};` + // document.cookie = `expires=${new Date(new Date().getTime() + (10000 * 60 * 60 * 7 * 24))};` + // document.cookie = `doamin=localhost;` + // }) + // .catch(() => { + // setIsAuthenticated(false) + // }) }, []); if (isAuthenticated === undefined) { diff --git a/src/index.tsx b/src/index.tsx index 3317238..5d3ec5b 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -3,13 +3,5 @@ import ReactDOM from "react-dom"; import Application from './App'; import "./styles.css"; -function App() { - return ( -
- -
- ); -} - const rootElement = document.getElementById("root"); -ReactDOM.render(, rootElement); +ReactDOM.render(, rootElement); diff --git a/src/reducer.ts b/src/reducer.ts deleted file mode 100644 index ea92eb4..0000000 --- a/src/reducer.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { Action, IState } from './store'; - -export default function reducer( - state: IState | null | undefined, - action: Action, -) { - if (!state) { - return null; - } - - switch (action.type) { - case 'UPDATE_AUTH_TOKEN': { - return { - ...state, - authToken: action.payload - }; - } - - case 'DELETE_AUTH_TOKEN': { - return { ...state, authToken: '' }; - } - - default: - return state; - } -} diff --git a/src/store.ts b/src/store.ts deleted file mode 100644 index 52b92d1..0000000 --- a/src/store.ts +++ /dev/null @@ -1,22 +0,0 @@ - -import { createStore } from 'redux'; -import reducer from './reducer'; - -export interface IState { - authToken: string -} - -export type Action = - | { - type: 'UPDATE_AUTH_TOKEN'; - payload: string; - } - | { - type: 'DELETE_AUTH_TOKEN'; - }; - -export function makeStore() { - return createStore(reducer, { - authToken: '' - }); -} diff --git a/tokenHandler.go b/tokenHandler.go new file mode 100644 index 0000000..41fe43d --- /dev/null +++ b/tokenHandler.go @@ -0,0 +1,67 @@ +package main + +import ( + "bytes" + "encoding/base64" + "encoding/json" + "net/http" + "net/url" + "os" + "strings" + + "github.com/gin-gonic/gin" +) + +type tokenRequestParams struct { + Code string `json:"code"` +} + +func tokenHandler(c *gin.Context) { + var reqParams tokenRequestParams + + if err := c.ShouldBindJSON(&reqParams); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + + client := &http.Client{} + data := url.Values{} + redirectURL := "http://localhost:3000/login-success" + data.Set("grant_type", "authorization_code") + data.Add("code", reqParams.Code) + data.Add("redirect_uri", redirectURL) + u, _ := url.ParseRequestURI("https://www.reddit.com") + u.Path = "/api/v1/access_token/" + urlString := u.String() + req, e := http.NewRequest("POST", urlString, bytes.NewBufferString(data.Encode())) + + if e != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": e}) + } + + authValue := strings.Join([]string{os.Getenv("CLIENT_ID"), os.Getenv("CLIENT_SECRET")}, ":") + basicToken := strings.Join([]string{"Basic", base64.StdEncoding.EncodeToString([]byte(authValue))}, " ") + req.Header.Set("Content-Type", "application/x-www-form-urlencoded; param=value") + req.Header.Set("Authorization", basicToken) + req.Header.Set("User-Agent", "leerlo v0.0.1 (by /u/aravind741)") + res, e := client.Do(req) + if e != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": e}) + } + + if res.StatusCode != http.StatusOK { + c.JSON(http.StatusUnauthorized, gin.H{}) + } + + var result map[string]interface{} + json.NewDecoder(res.Body).Decode(&result) + + if result["access_token"] == nil { + c.JSON(http.StatusUnauthorized, gin.H{}) + } else { + c.JSON(http.StatusOK, gin.H{ + "access_token": result["access_token"], + "refresh_token": result["refresh_token"], + }) + } +} From 43ab09a0e0f135193d2c5098635434966156e0ea Mon Sep 17 00:00:00 2001 From: thearavind Date: Tue, 7 May 2019 01:29:21 +0530 Subject: [PATCH 2/2] Enable get access token api call --- src/Redirect.tsx | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/Redirect.tsx b/src/Redirect.tsx index 48d73dd..bbb322a 100644 --- a/src/Redirect.tsx +++ b/src/Redirect.tsx @@ -5,23 +5,23 @@ const LoginSuccess = (props: any) => { let defaultValue: boolean | undefined const [isAuthenticated, setIsAuthenticated] = useState(defaultValue); useEffect(() => { - // let params = new URLSearchParams(props.location.search) - // const authToken = params.get('code') - // fetch(`/generate_token`, { - // method: 'POST', - // body: JSON.stringify({ code: authToken }) - // }) - // .then(res => res.json()) - // .then((response) => { - // setIsAuthenticated(true) - // document.cookie = `accessToken=${response.access_token};` - // document.cookie = `refreshToken=${response.refresh_token};` - // document.cookie = `expires=${new Date(new Date().getTime() + (10000 * 60 * 60 * 7 * 24))};` - // document.cookie = `doamin=localhost;` - // }) - // .catch(() => { - // setIsAuthenticated(false) - // }) + let params = new URLSearchParams(props.location.search) + const authToken = params.get('code') + fetch(`/api/generate_token`, { + method: 'POST', + body: JSON.stringify({ code: authToken }) + }) + .then(res => res.json()) + .then((response) => { + setIsAuthenticated(true) + document.cookie = `accessToken=${response.access_token};` + document.cookie = `refreshToken=${response.refresh_token};` + document.cookie = `expires=${new Date(new Date().getTime() + (10000 * 60 * 60 * 7 * 24))};` + document.cookie = `doamin=localhost;` + }) + .catch(() => { + setIsAuthenticated(false) + }) }, []); if (isAuthenticated === undefined) {