added more stuff
This commit is contained in:
parent
2e773d3c7e
commit
44d75030aa
30
auth/auth.go
30
auth/auth.go
@ -48,7 +48,7 @@ func signToken(token TokenInfo) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func hashPassword(password string) (string, error) {
|
func hashPassword(password string) (string, error) {
|
||||||
bytes, err := bcrypt.GenerateFromPassword([]byte(password), 14)
|
bytes, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
||||||
return string(bytes), err
|
return string(bytes), err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,16 +63,19 @@ func AuthorizedTo(requiredPermissions models.Permission) gin.HandlerFunc {
|
|||||||
token, err := jwt.ParseWithClaims(authCookie.Value, &AuthClaims{}, func(token *jwt.Token) (interface{}, error) {
|
token, err := jwt.ParseWithClaims(authCookie.Value, &AuthClaims{}, func(token *jwt.Token) (interface{}, error) {
|
||||||
// Don't forget to validate the alg is what you expect:
|
// Don't forget to validate the alg is what you expect:
|
||||||
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
|
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
|
||||||
return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
|
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
|
||||||
}
|
}
|
||||||
|
|
||||||
// hmacSampleSecret is a []byte containing your secret, e.g. []byte("my_secret_key")
|
// hmacSampleSecret is a []byte containing your secret, e.g. []byte("my_secret_key")
|
||||||
return hmacSampleSecret, nil
|
return hmacSampleSecret, nil
|
||||||
})
|
})
|
||||||
|
if err != nil {
|
||||||
|
ctx.AbortWithError(403, err)
|
||||||
|
}
|
||||||
fmt.Println(token.Claims)
|
fmt.Println(token.Claims)
|
||||||
if claims, ok := token.Claims.(*AuthClaims); ok && token.Valid {
|
if claims, ok := token.Claims.(*AuthClaims); ok && token.Valid {
|
||||||
ctx.Set("claims", claims)
|
ctx.Set("claims", claims)
|
||||||
if requiredPermissions&claims.Permissions != requiredPermissions {
|
if requiredPermissions&claims.Permissions != requiredPermissions && models.Admin&claims.Permissions != models.Admin {
|
||||||
ctx.AbortWithStatus(403)
|
ctx.AbortWithStatus(403)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -104,29 +107,32 @@ func (con Connection) signUp(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type SignInRequest struct {
|
type SignInRequest struct {
|
||||||
username string
|
Username string `json:"username"`
|
||||||
password string
|
Password string `json:"password"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (con Connection) signIn(c *gin.Context) {
|
func (con Connection) signIn(c *gin.Context) {
|
||||||
|
|
||||||
type signInRequest struct {
|
var request SignInRequest
|
||||||
username string
|
|
||||||
password string
|
|
||||||
}
|
|
||||||
var request signInRequest
|
|
||||||
err := json.NewDecoder(c.Request.Body).Decode(&request)
|
err := json.NewDecoder(c.Request.Body).Decode(&request)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(500, err)
|
c.AbortWithError(500, err)
|
||||||
}
|
}
|
||||||
var userItem models.User
|
var userItem models.User
|
||||||
err = con.connection.Database("Backend").Collection("Users").FindOne(context.TODO(), bson.D{{Key: "username", Value: request.username}}).Decode(&userItem)
|
err = con.connection.Database("Backend").Collection("Users").FindOne(context.TODO(), bson.D{{Key: "Username", Value: request.Username}}).Decode(&userItem)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(403, err)
|
c.AbortWithError(403, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if hashedPass, err := hashPassword(request.password); err != nil || userItem.HashedPass != hashedPass {
|
err = bcrypt.CompareHashAndPassword([]byte(userItem.HashedPass), []byte(request.Password))
|
||||||
|
if err != nil {
|
||||||
|
println(err.Error())
|
||||||
|
pass, err := hashPassword(request.Password)
|
||||||
|
if err != nil {
|
||||||
|
c.AbortWithError(403, err)
|
||||||
|
}
|
||||||
|
fmt.Printf("UserPass: %s\nDatabaseHash: %s\nHash %s\n", request.Password, userItem.HashedPass, pass)
|
||||||
c.AbortWithStatus(403)
|
c.AbortWithStatus(403)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
1
go.mod
1
go.mod
@ -7,6 +7,7 @@ require github.com/gin-gonic/gin v1.9.1
|
|||||||
require (
|
require (
|
||||||
github.com/bytedance/sonic v1.9.1 // indirect
|
github.com/bytedance/sonic v1.9.1 // indirect
|
||||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
|
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
|
||||||
|
github.com/docker/docker v26.1.2+incompatible // indirect
|
||||||
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
|
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
|
||||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||||
github.com/go-oas/docs v1.1.0 // indirect
|
github.com/go-oas/docs v1.1.0 // indirect
|
||||||
|
2
go.sum
2
go.sum
@ -6,6 +6,8 @@ github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhD
|
|||||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
|
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/docker/docker v26.1.2+incompatible h1:UVX5ZOrrfTGZZYEP+ZDq3Xn9PdHNXaSYMFPDumMqG2k=
|
||||||
|
github.com/docker/docker v26.1.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||||
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
|
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
|
||||||
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
|
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
|
||||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||||
|
@ -6,13 +6,17 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"acooldomain.co/backend/auth"
|
||||||
"acooldomain.co/backend/models"
|
"acooldomain.co/backend/models"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"github.com/docker/docker/api/types/container"
|
"github.com/docker/docker/api/types/container"
|
||||||
"github.com/docker/docker/api/types/filters"
|
"github.com/docker/docker/api/types/filters"
|
||||||
|
"github.com/docker/docker/api/types/mount"
|
||||||
|
"github.com/docker/docker/api/types/network"
|
||||||
"github.com/docker/docker/api/types/volume"
|
"github.com/docker/docker/api/types/volume"
|
||||||
"github.com/docker/docker/client"
|
"github.com/docker/docker/client"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
"go.mongodb.org/mongo-driver/bson"
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
"go.mongodb.org/mongo-driver/mongo"
|
"go.mongodb.org/mongo-driver/mongo"
|
||||||
)
|
)
|
||||||
@ -32,12 +36,66 @@ type ContainerLabels struct {
|
|||||||
type VolumeLabels struct {
|
type VolumeLabels struct {
|
||||||
OwnerId string `json:"user_id"`
|
OwnerId string `json:"user_id"`
|
||||||
ImageId string `json:"image_id"`
|
ImageId string `json:"image_id"`
|
||||||
|
Type string `json:"type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ImageLabels struct {
|
type ImageLabels struct {
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (con Connection) getServerInfo(volume volume.Volume) (*models.ServerInfo, error) {
|
||||||
|
var volumeLabels VolumeLabels
|
||||||
|
jsonData, err := json.Marshal(volume.Labels)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
json.Unmarshal(jsonData, &volumeLabels)
|
||||||
|
|
||||||
|
imageNameAndVersion := strings.Split(volumeLabels.ImageId, ":")
|
||||||
|
|
||||||
|
imageName := imageNameAndVersion[0]
|
||||||
|
imageVersion := imageNameAndVersion[1]
|
||||||
|
containers, err := con.apiClient.ContainerList(context.Background(), container.ListOptions{
|
||||||
|
All: true,
|
||||||
|
Filters: filters.NewArgs(filters.Arg("label", "type=GAME"), filters.Arg("label", fmt.Sprintf("volume_id=%s", volume.Name))),
|
||||||
|
})
|
||||||
|
var state bool
|
||||||
|
var ports []models.Port
|
||||||
|
if err != nil || len(containers) == 0 {
|
||||||
|
state = false
|
||||||
|
ports = nil
|
||||||
|
} else {
|
||||||
|
container := containers[0]
|
||||||
|
state = container.State == "running"
|
||||||
|
ports = transformContainerPortsToModel(container.Ports)
|
||||||
|
}
|
||||||
|
var serverData models.ServerData
|
||||||
|
con.connection.Database("backend").Collection("servers").FindOne(context.TODO(), bson.D{{Key: "volume_id", Value: volume.Name}}).Decode(&serverData)
|
||||||
|
|
||||||
|
serverInfo := models.ServerInfo{
|
||||||
|
Id: volume.Name,
|
||||||
|
Image: models.ImageInfo{
|
||||||
|
Name: imageName,
|
||||||
|
Version: imageVersion,
|
||||||
|
},
|
||||||
|
OwnerId: volumeLabels.OwnerId,
|
||||||
|
On: state,
|
||||||
|
Ports: ports,
|
||||||
|
Nickname: serverData.Nickname,
|
||||||
|
}
|
||||||
|
return &serverInfo, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (con Connection) getServerInfoFromId(ServerId string) (*models.ServerInfo, error) {
|
||||||
|
volume, err := con.apiClient.VolumeInspect(context.Background(), ServerId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return con.getServerInfo(volume)
|
||||||
|
}
|
||||||
|
|
||||||
func transformContainerPortsToModel(ports []types.Port) []models.Port {
|
func transformContainerPortsToModel(ports []types.Port) []models.Port {
|
||||||
modelPorts := make([]models.Port, len(ports))
|
modelPorts := make([]models.Port, len(ports))
|
||||||
for index, port := range ports {
|
for index, port := range ports {
|
||||||
@ -49,6 +107,74 @@ func transformContainerPortsToModel(ports []types.Port) []models.Port {
|
|||||||
return modelPorts
|
return modelPorts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (con Connection) StartServer(ctx *gin.Context) {
|
||||||
|
serverId := ctx.Param("server_id")
|
||||||
|
claims, exists := ctx.Get("claims")
|
||||||
|
if !exists {
|
||||||
|
ctx.AbortWithStatus(403)
|
||||||
|
}
|
||||||
|
|
||||||
|
// command := ctx.Param("command")
|
||||||
|
|
||||||
|
serverInfo, err := con.getServerInfoFromId(serverId)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
ctx.AbortWithError(500, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if serverInfo.On {
|
||||||
|
ctx.Status(200)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
imageId := serverInfo.Image.Name + ":" + serverInfo.Image.Version
|
||||||
|
labels := ContainerLabels{
|
||||||
|
OwnerId: claims.(*auth.AuthClaims).Username,
|
||||||
|
ImageId: imageId,
|
||||||
|
VolumeId: serverInfo.Id,
|
||||||
|
Type: "GAME",
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonString, err := json.Marshal(labels)
|
||||||
|
if err != nil {
|
||||||
|
ctx.AbortWithError(500, err)
|
||||||
|
}
|
||||||
|
jsonLabels := make(map[string]string)
|
||||||
|
json.Unmarshal(jsonString, &jsonLabels)
|
||||||
|
|
||||||
|
volumes := make(map[string]struct{})
|
||||||
|
|
||||||
|
image, _, err := con.apiClient.ImageInspectWithRaw(context.Background(), imageId)
|
||||||
|
if err != nil {
|
||||||
|
ctx.AbortWithError(500, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
response, err := con.apiClient.ContainerCreate(
|
||||||
|
context.Background(),
|
||||||
|
&container.Config{
|
||||||
|
AttachStdin: true,
|
||||||
|
AttachStdout: true,
|
||||||
|
AttachStderr: true,
|
||||||
|
Tty: true,
|
||||||
|
OpenStdin: false,
|
||||||
|
StdinOnce: false,
|
||||||
|
Image: imageId,
|
||||||
|
Volumes: volumes,
|
||||||
|
Labels: jsonLabels,
|
||||||
|
},
|
||||||
|
&container.HostConfig{
|
||||||
|
AutoRemove: false,
|
||||||
|
Mounts: []mount.Mount{{Source: serverInfo.Id, Target: image.Config.WorkingDir, Type: "volume"}},
|
||||||
|
},
|
||||||
|
&network.NetworkingConfig{},
|
||||||
|
&v1.Platform{},
|
||||||
|
"",
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
ctx.AbortWithError(500, err)
|
||||||
|
}
|
||||||
|
ctx.JSON(200, response.ID)
|
||||||
|
}
|
||||||
|
|
||||||
func (con Connection) GetServers(ctx *gin.Context) {
|
func (con Connection) GetServers(ctx *gin.Context) {
|
||||||
volumes, err := con.apiClient.VolumeList(
|
volumes, err := con.apiClient.VolumeList(
|
||||||
context.TODO(),
|
context.TODO(),
|
||||||
@ -59,48 +185,14 @@ func (con Connection) GetServers(ctx *gin.Context) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.AbortWithError(500, err)
|
ctx.AbortWithError(500, err)
|
||||||
}
|
}
|
||||||
var volumeLabels VolumeLabels
|
|
||||||
var servers []models.ServerInfo
|
var servers []models.ServerInfo
|
||||||
println("Found %d Containers", len(volumes.Volumes))
|
println("Found %d Containers", len(volumes.Volumes))
|
||||||
for _, volume := range volumes.Volumes {
|
for _, volume := range volumes.Volumes {
|
||||||
jsonData, err := json.Marshal(volume.Labels)
|
serverInfo, err := con.getServerInfo(*volume)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
json.Unmarshal(jsonData, &volumeLabels)
|
servers = append(servers, *serverInfo)
|
||||||
|
|
||||||
imageNameAndVersion := strings.Split(volumeLabels.ImageId, ":")
|
|
||||||
|
|
||||||
imageName := imageNameAndVersion[0]
|
|
||||||
imageVersion := imageNameAndVersion[1]
|
|
||||||
containers, err := con.apiClient.ContainerList(context.Background(), container.ListOptions{
|
|
||||||
All: true,
|
|
||||||
Filters: filters.NewArgs(filters.Arg("label", "type=GAME"), filters.Arg("label", fmt.Sprintf("volume_id=%s", volume.Name))),
|
|
||||||
})
|
|
||||||
var state bool
|
|
||||||
var ports []models.Port
|
|
||||||
if err != nil || len(containers) == 0 {
|
|
||||||
state = false
|
|
||||||
ports = nil
|
|
||||||
} else {
|
|
||||||
container := containers[0]
|
|
||||||
state = container.State == "running"
|
|
||||||
ports = container.Ports
|
|
||||||
}
|
|
||||||
var serverData models.ServerData
|
|
||||||
con.connection.Database("backend").Collection("servers").FindOne(context.TODO(), bson.D{{Key: "volume_id", Value: volume.Name}}).Decode(&serverData)
|
|
||||||
|
|
||||||
servers = append(servers, models.ServerInfo{
|
|
||||||
Id: volume.Name,
|
|
||||||
Image: models.ImageInfo{
|
|
||||||
Name: imageName,
|
|
||||||
Version: imageVersion,
|
|
||||||
},
|
|
||||||
OwnerId: volumeLabels.OwnerId,
|
|
||||||
On: state,
|
|
||||||
Ports: ports,
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -111,12 +203,13 @@ func (con Connection) GetServers(ctx *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func LoadGroup(group *gin.RouterGroup, mongo_client *mongo.Client) {
|
func LoadGroup(group *gin.RouterGroup, mongo_client *mongo.Client) {
|
||||||
apiClient, err := client.NewClientWithOpts(client.FromEnv)
|
apiClient, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
defer apiClient.Close()
|
defer apiClient.Close()
|
||||||
|
|
||||||
connection := Connection{connection: mongo_client, apiClient: apiClient}
|
connection := Connection{connection: mongo_client, apiClient: apiClient}
|
||||||
|
group.Use(auth.AuthorizedTo(models.Create)).POST("/:server_id/start", connection.StartServer)
|
||||||
group.GET("/", connection.GetServers)
|
group.GET("/", connection.GetServers)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user