update
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -3,3 +3,4 @@ __debug_bin
|
||||
.env
|
||||
.idea
|
||||
output
|
||||
docs
|
||||
@@ -1,7 +0,0 @@
|
||||
connectivity_policy {
|
||||
allow_deployments_to_no_targets = true
|
||||
}
|
||||
|
||||
versioning_strategy {
|
||||
template = "#{Octopus.Version.LastMajor}.#{Octopus.Version.LastMinor}.#{Octopus.Version.NextPatch}"
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
version = 6
|
||||
@@ -1,3 +0,0 @@
|
||||
variable "TestVariable" {
|
||||
value "1234" {}
|
||||
}
|
||||
@@ -1,10 +1,8 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/joho/godotenv"
|
||||
openai "github.com/sashabaranov/go-openai"
|
||||
)
|
||||
|
||||
@@ -12,23 +10,33 @@ type Controller struct {
|
||||
openaiClient *openai.Client
|
||||
unraidAPIKey string
|
||||
unraidURI string
|
||||
ClientID string
|
||||
ClientSecret string
|
||||
RedirectURL string
|
||||
AuthURL string
|
||||
TokenURL string
|
||||
}
|
||||
|
||||
func NewController() *Controller {
|
||||
err := godotenv.Load(".env")
|
||||
|
||||
openaiApiKey := os.Getenv("OPENAI_API_KEY")
|
||||
openaiClient := openai.NewClient(openaiApiKey)
|
||||
unraidAPIKey := os.Getenv("UNRAID_API_KEY")
|
||||
unraidURI := os.Getenv("UNRAID_URI")
|
||||
ClientID := os.Getenv("ClientID")
|
||||
ClientSecret := os.Getenv("ClientSecret")
|
||||
RedirectURL := os.Getenv("RedirectURL")
|
||||
AuthURL := os.Getenv("AuthURL")
|
||||
TokenURL := os.Getenv("TokenURL")
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(".env file not found, using environment variables")
|
||||
}
|
||||
return &Controller{
|
||||
openaiClient: openaiClient,
|
||||
openaiClient: openai.NewClient(openaiApiKey),
|
||||
unraidAPIKey: unraidAPIKey,
|
||||
unraidURI: unraidURI,
|
||||
ClientID: ClientID,
|
||||
ClientSecret: ClientSecret,
|
||||
RedirectURL: RedirectURL,
|
||||
AuthURL: AuthURL,
|
||||
TokenURL: TokenURL,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
25
controller/token.go
Normal file
25
controller/token.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
// GenerateToken godoc
|
||||
//
|
||||
// @Summary Generate Health status
|
||||
// @Description Get the health of the API
|
||||
// @Tags token
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {string} json "response"
|
||||
// @Router /token/GenerateToken [get]
|
||||
func (c *Controller) GenerateToken(conf *oauth2.Config) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
// Redirect user to the authorization URL
|
||||
authURL := conf.AuthCodeURL("state", oauth2.AccessTypeOffline)
|
||||
c.Redirect(http.StatusTemporaryRedirect, authURL)
|
||||
}
|
||||
}
|
||||
25
docs/docs.go
25
docs/docs.go
@@ -112,6 +112,29 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"/token/GenerateToken": {
|
||||
"get": {
|
||||
"description": "Get the health of the API",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"token"
|
||||
],
|
||||
"summary": "Generate Health status",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "response",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/unraid/powerusage": {
|
||||
"get": {
|
||||
"description": "Gets the PSU Data from unraid",
|
||||
@@ -148,7 +171,7 @@ const docTemplate = `{
|
||||
// SwaggerInfo holds exported Swagger Info so clients can modify it
|
||||
var SwaggerInfo = &swag.Spec{
|
||||
Version: "1.0",
|
||||
Host: "durpapi.durp.info",
|
||||
Host: "localhost:8080",
|
||||
BasePath: "/api/v1",
|
||||
Schemes: []string{},
|
||||
Title: "DurpAPI",
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
},
|
||||
"version": "1.0"
|
||||
},
|
||||
"host": "durpapi.durp.info",
|
||||
"host": "localhost:8080",
|
||||
"basePath": "/api/v1",
|
||||
"paths": {
|
||||
"/health/getHealth": {
|
||||
@@ -105,6 +105,29 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/token/GenerateToken": {
|
||||
"get": {
|
||||
"description": "Get the health of the API",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"token"
|
||||
],
|
||||
"summary": "Generate Health status",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "response",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/unraid/powerusage": {
|
||||
"get": {
|
||||
"description": "Gets the PSU Data from unraid",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
basePath: /api/v1
|
||||
host: durpapi.durp.info
|
||||
host: localhost:8080
|
||||
info:
|
||||
contact:
|
||||
email: support@swagger.io
|
||||
@@ -70,6 +70,21 @@ paths:
|
||||
summary: Travel Agent ChatGPT
|
||||
tags:
|
||||
- openai
|
||||
/token/GenerateToken:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Get the health of the API
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: response
|
||||
schema:
|
||||
type: string
|
||||
summary: Generate Health status
|
||||
tags:
|
||||
- token
|
||||
/unraid/powerusage:
|
||||
get:
|
||||
consumes:
|
||||
|
||||
11
go.mod
11
go.mod
@@ -11,7 +11,11 @@ require (
|
||||
github.com/swaggo/swag v1.8.12
|
||||
)
|
||||
|
||||
require github.com/google/go-cmp v0.5.8 // indirect
|
||||
require (
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/google/go-cmp v0.5.8 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/KyleBanks/depth v1.2.1 // indirect
|
||||
@@ -43,8 +47,9 @@ require (
|
||||
github.com/ugorji/go/codec v1.2.9 // indirect
|
||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect
|
||||
golang.org/x/crypto v0.5.0 // indirect
|
||||
golang.org/x/net v0.9.0 // indirect
|
||||
golang.org/x/sys v0.7.0 // indirect
|
||||
golang.org/x/net v0.10.0 // indirect
|
||||
golang.org/x/oauth2 v0.8.0
|
||||
golang.org/x/sys v0.8.0 // indirect
|
||||
golang.org/x/text v0.9.0 // indirect
|
||||
golang.org/x/tools v0.7.0 // indirect
|
||||
google.golang.org/protobuf v1.28.1 // indirect
|
||||
|
||||
14
go.sum
14
go.sum
@@ -42,7 +42,10 @@ github.com/goccy/go-json v0.10.0 h1:mXKd9Qw4NuzShiRlOXKews24ufknHO7gx30lsDyokKA=
|
||||
github.com/goccy/go-json v0.10.0/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA=
|
||||
github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
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/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
|
||||
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
@@ -110,6 +113,7 @@ golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE=
|
||||
golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM=
|
||||
@@ -117,6 +121,10 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug
|
||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
|
||||
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
||||
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8=
|
||||
golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -129,10 +137,13 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
|
||||
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
@@ -146,7 +157,10 @@ golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4=
|
||||
golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
|
||||
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
|
||||
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
||||
93
main.go
93
main.go
@@ -1,16 +1,16 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
swaggerFiles "github.com/swaggo/files"
|
||||
ginSwagger "github.com/swaggo/gin-swagger"
|
||||
"gitlab.com/DeveloperDurp/DurpAPI/controller"
|
||||
_ "gitlab.com/DeveloperDurp/DurpAPI/docs"
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
// @title DurpAPI
|
||||
@@ -37,6 +37,19 @@ func main() {
|
||||
r := gin.Default()
|
||||
c := controller.NewController()
|
||||
var groups []string
|
||||
conf := &oauth2.Config{
|
||||
ClientID: c.ClientID,
|
||||
ClientSecret: c.ClientSecret,
|
||||
RedirectURL: c.RedirectURL,
|
||||
Scopes: []string{
|
||||
"email",
|
||||
"groups",
|
||||
},
|
||||
Endpoint: oauth2.Endpoint{
|
||||
AuthURL: c.AuthURL,
|
||||
TokenURL: c.TokenURL,
|
||||
},
|
||||
}
|
||||
|
||||
v1 := r.Group("/api/v1")
|
||||
{
|
||||
@@ -44,6 +57,10 @@ func main() {
|
||||
{
|
||||
health.GET("getHealth", c.GetHealth)
|
||||
}
|
||||
token := v1.Group("/token")
|
||||
{
|
||||
token.GET("GenerateToken", c.GenerateToken(conf))
|
||||
}
|
||||
openai := v1.Group("/openai")
|
||||
{
|
||||
groups = []string{"openai"}
|
||||
@@ -59,52 +76,62 @@ func main() {
|
||||
}
|
||||
}
|
||||
r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
|
||||
r.GET("/callback", CallbackHandler(conf))
|
||||
|
||||
err := r.Run(":8080")
|
||||
if err != nil {
|
||||
fmt.Println("Failed to start server")
|
||||
}
|
||||
}
|
||||
|
||||
func authMiddleware(allowedGroups []string) gin.HandlerFunc {
|
||||
func authMiddleware(groups []string) gin.HandlerFunc {
|
||||
|
||||
return func(c *gin.Context) {
|
||||
|
||||
var groups []string
|
||||
groupsenv := os.Getenv("groups")
|
||||
if groupsenv != "" {
|
||||
groups = strings.Split(groupsenv, ",")
|
||||
} else {
|
||||
// Get the user groups from the request headers
|
||||
groupsHeader := c.GetHeader("X-authentik-groups")
|
||||
|
||||
// Split the groups header value into individual groups
|
||||
groups = strings.Split(groupsHeader, "|")
|
||||
// Get the access token from the request header or query parameters
|
||||
accessToken := c.GetHeader("Authorization")
|
||||
if accessToken == "" {
|
||||
accessToken = c.Query("access_token")
|
||||
}
|
||||
|
||||
// Check if the user belongs to any of the allowed groups
|
||||
isAllowed := false
|
||||
for _, allowedGroup := range allowedGroups {
|
||||
for _, group := range groups {
|
||||
if group == allowedGroup {
|
||||
isAllowed = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if isAllowed {
|
||||
break
|
||||
}
|
||||
}
|
||||
// Create an OAuth2 token from the access token
|
||||
token := &oauth2.Token{AccessToken: accessToken}
|
||||
|
||||
// If the user is not in any of the allowed groups, respond with unauthorized access
|
||||
if !isAllowed {
|
||||
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{
|
||||
"message": "Unauthorized access",
|
||||
"groups": groups,
|
||||
})
|
||||
// Validate the token
|
||||
if !token.Valid() {
|
||||
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"})
|
||||
return
|
||||
}
|
||||
|
||||
// Add the token to the request context for later use
|
||||
ctx := context.WithValue(c.Request.Context(), "token", token)
|
||||
c.Request = c.Request.WithContext(ctx)
|
||||
|
||||
// Call the next handler
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
// CallbackHandler receives the authorization code and exchanges it for a token
|
||||
func CallbackHandler(conf *oauth2.Config) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
// Get the authorization code from the query parameters
|
||||
code := c.Query("code")
|
||||
|
||||
// Exchange the authorization code for a token
|
||||
token, err := conf.Exchange(context.Background(), code)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to exchange authorization code"})
|
||||
return
|
||||
}
|
||||
|
||||
// Create a response JSON
|
||||
response := gin.H{
|
||||
"access_token": token.AccessToken,
|
||||
"token_type": token.TokenType,
|
||||
"refresh_token": token.RefreshToken,
|
||||
"expiry": token.Expiry,
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user