Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sprint8 #3

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions API/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# syntax=docker/dockerfile:1

FROM golang:latest

# Set destination for COPY
WORKDIR /app

# Download Go modules
COPY go.mod go.sum ./
RUN go mod download

# Copy the source code. Note the slash at the end, as explained in
# https://docs.docker.com/reference/dockerfile/#copy
COPY *.go ./

# Build
RUN CGO_ENABLED=0 GOOS=linux go build -o /api

# Optional:
# To bind to a TCP port, runtime parameters must be supplied to the docker command.
# But we can document in the Dockerfile what ports
# the application is going to listen on by default.
# https://docs.docker.com/reference/dockerfile/#expose
EXPOSE 8090

# Run
CMD ["/api"]
58 changes: 58 additions & 0 deletions API/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
module api

go 1.23.1

require (
github.com/gin-contrib/cors v1.7.2
github.com/gin-gonic/gin v1.10.0
github.com/spf13/viper v1.19.0
github.com/tbaehler/gin-keycloak v1.6.1
)

require (
github.com/bytedance/sonic v1.11.6 // indirect
github.com/bytedance/sonic/loader v0.1.1 // indirect
github.com/cloudwego/base64x v0.1.4 // indirect
github.com/cloudwego/iasm v0.2.0 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.20.0 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/golang/glog v1.2.1 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/afero v1.11.0 // indirect
github.com/spf13/cast v1.6.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.12 // indirect
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.9.0 // indirect
golang.org/x/arch v0.8.0 // indirect
golang.org/x/crypto v0.23.0 // indirect
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
golang.org/x/net v0.25.0 // indirect
golang.org/x/oauth2 v0.19.0 // indirect
golang.org/x/sys v0.20.0 // indirect
golang.org/x/text v0.15.0 // indirect
google.golang.org/protobuf v1.34.1 // indirect
gopkg.in/go-jose/go-jose.v2 v2.6.3 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
1,708 changes: 1,708 additions & 0 deletions API/go.sum

Large diffs are not rendered by default.

114 changes: 114 additions & 0 deletions API/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package main

import (
"context"
"fmt"
"log"
"net/http"
"os"
"os/signal"
"syscall"
"time"

"github.com/gin-contrib/cors"
"github.com/gin-gonic/gin"
"github.com/spf13/viper"
"github.com/tbaehler/gin-keycloak/pkg/ginkeycloak"
)

const (
CFG_PORT = "port"
CFG_PORT_DEFAULT = "8090"
CFG_KEYCLOAK_URL = "keycloak_url"
CFG_KEYCLOAK_URL_DEFAULT = "http://192.168.68.104:8080"
CFG_KEYCLOAK_REALM = "keycloak_realm"
CFG_KEYCLOAK_REALM_DEFAULT = "reports-realm"
CFG_KEYCLOAK_CLIENT = "keycloak_client"
CFG_KEYCLOAK_CLIENT_DEFAULT = "reports-api"
CFG_ALLOW_ROLE = "allow_role"
CFG_ALLOW_ROLE_DEFAULT = "prothetic_user"
)

func CORSMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
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-Methods", "POST, OPTIONS, GET, PUT")

if c.Request.Method == "OPTIONS" {
c.AbortWithStatus(204)
return
}

c.Next()
}
}

func main() {

// Prepare config
viper.SetDefault(CFG_PORT, CFG_PORT_DEFAULT)
viper.SetDefault(CFG_KEYCLOAK_URL, CFG_KEYCLOAK_URL_DEFAULT)
viper.SetDefault(CFG_KEYCLOAK_REALM, CFG_KEYCLOAK_REALM_DEFAULT)
viper.SetDefault(CFG_KEYCLOAK_CLIENT, CFG_KEYCLOAK_CLIENT_DEFAULT)
viper.SetDefault(CFG_ALLOW_ROLE, CFG_ALLOW_ROLE_DEFAULT)
viper.AutomaticEnv()

// Prepare router
router := gin.Default()
router.Use(ginkeycloak.RequestLogger([]string{"uid"}, "data"))
router.Use(gin.Recovery())
router.Use(cors.Default())

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

тут используется cors.Default().
В Default Authorization header запрещён https://github.com/gin-contrib/cors/blob/master/cors.go#L179

В итоге при авторизации через protheric1 и скачивании отчёта, ловлю следующую ошибку:
"Access to fetch at 'http://localhost:8090/reports/' from origin 'http://localhost:3000' has been blocked by CORS policy: Request header field authorization is not allowed by Access-Control-Allow-Headers in preflight response."
image

Нужно поправить cors


// Prepare keycloack
keycloackConfig := ginkeycloak.BuilderConfig{
Url: viper.GetString(CFG_KEYCLOAK_URL),
Realm: viper.GetString(CFG_KEYCLOAK_REALM),
}

// Add private api
privateApi := router.Group("/reports")
privateApi.Use(
ginkeycloak.NewAccessBuilder(keycloackConfig).
RestrictButForRealm(viper.GetString(CFG_ALLOW_ROLE)).Build(),
)
privateApi.GET("/", func(ctx *gin.Context) {
ctx.JSON(http.StatusOK, "ok")
})

// Prepare server
srv := &http.Server{
Addr: fmt.Sprintf(":%v", viper.GetInt(CFG_PORT)),
Handler: router.Handler(),
}

go func() {
// service connections
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatalf("listen: %s\n", err)
}
}()

// Wait for interrupt signal to gracefully shutdown the server with
// a timeout of 5 seconds.
quit := make(chan os.Signal, 1)
// kill (no param) default send syscall.SIGTERM
// kill -2 is syscall.SIGINT
// kill -9 is syscall. SIGKILL but can"t be catch, so don't need add it
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
log.Println("Shutdown Server ...")

ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := srv.Shutdown(ctx); err != nil {
log.Fatal("Server Shutdown:", err)
}
// catching ctx.Done(). timeout of 5 seconds.
select {
case <-ctx.Done():
log.Println("timeout of 5 seconds.")
}
log.Println("Server exiting")
}
15 changes: 13 additions & 2 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,18 @@ services:
ports:
- "3000:3000"
environment:
REACT_APP_API_URL: http://localhost:8000
REACT_APP_KEYCLOAK_URL: http://localhost:8080
REACT_APP_API_URL: http://keycloak:8000
REACT_APP_KEYCLOAK_URL: http://keycloak:8080
REACT_APP_KEYCLOAK_REALM: reports-realm
REACT_APP_KEYCLOAK_CLIENT_ID: reports-frontend
backend:
build:
context: ./API
dockerfile: Dockerfile
ports:
- "8090:8090"
environment:
- keycloak_url=http://keycloak:8080
- keycloak_realm=reports-realm
- keycloak_client=reports-api
- allow_role=prothetic_user
6 changes: 3 additions & 3 deletions frontend/.env
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
REACT_APP_API_URL=http://localhost:8000
REACT_APP_KEYCLOAK_URL=http://localhost:8080
REACT_APP_API_URL=http://192.168.68.104:8090

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

тут хардкод айпишников, так лучше не делать

REACT_APP_KEYCLOAK_URL=http://192.168.68.104:8080
REACT_APP_KEYCLOAK_REALM=reports-realm
REACT_APP_KEYCLOAK_CLIENT_ID=reports-frontend
REACT_APP_KEYCLOAK_CLIENT_ID=reports-frontend
15 changes: 12 additions & 3 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,25 @@ import React from 'react';
import { ReactKeycloakProvider } from '@react-keycloak/web';
import Keycloak, { KeycloakConfig } from 'keycloak-js';
import ReportPage from './components/ReportPage';
import { useEffect } from "react";

const keycloakConfig: KeycloakConfig = {
url: process.env.REACT_APP_KEYCLOAK_URL,
realm: process.env.REACT_APP_KEYCLOAK_REALM||"",
clientId: process.env.REACT_APP_KEYCLOAK_CLIENT_ID||""
realm: process.env.REACT_APP_KEYCLOAK_REALM || "",
clientId: process.env.REACT_APP_KEYCLOAK_CLIENT_ID || ""
};

const keycloak = new Keycloak(keycloakConfig);

const App: React.FC = () => {

useEffect(() => {
keycloak.init({
pkceMethod: "S256",
});

}, [])

return (
<ReactKeycloakProvider authClient={keycloak}>
<div className="App">
Expand All @@ -21,4 +30,4 @@ const App: React.FC = () => {
);
};

export default App;
export default App;
2 changes: 1 addition & 1 deletion frontend/src/components/ReportPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const ReportPage: React.FC = () => {
setLoading(true);
setError(null);

const response = await fetch(`${process.env.REACT_APP_API_URL}/reports`, {
const response = await fetch(`${process.env.REACT_APP_API_URL}/reports/`, {
headers: {
'Authorization': `Bearer ${keycloak.token}`
}
Expand Down
6 changes: 3 additions & 3 deletions keycloak/realm-export.json
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,8 @@
"clientId": "reports-frontend",
"enabled": true,
"publicClient": true,
"redirectUris": ["http://localhost:3000/*"],
"webOrigins": ["http://localhost:3000"],
"redirectUris": ["http://192.168.68.104:3000/*"],

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

тут тоже

"webOrigins": ["http://192.168.68.104:3000"],
"directAccessGrantsEnabled": true
},
{
Expand All @@ -126,4 +126,4 @@
"bearerOnly": true
}
]
}
}