Rewrote the entire blob storage service, made auth not use MarshalBinary, which is useless, and made the Start button in captchaDiv the correct colour and same size as it's surrounding elements
Signed-off-by: arzumify <jliwin98@danwin1210.de>
This commit is contained in:
parent
d302745c9a
commit
13d00e8222
4
go.mod
4
go.mod
|
@ -4,7 +4,7 @@ go 1.23.1
|
||||||
|
|
||||||
require (
|
require (
|
||||||
git.ailur.dev/ailur/fg-library/v2 v2.1.1
|
git.ailur.dev/ailur/fg-library/v2 v2.1.1
|
||||||
git.ailur.dev/ailur/fg-nucleus-library v1.0.3
|
git.ailur.dev/ailur/fg-nucleus-library v1.0.4
|
||||||
git.ailur.dev/ailur/pow v1.0.2
|
git.ailur.dev/ailur/pow v1.0.2
|
||||||
github.com/CAFxX/httpcompression v0.0.9
|
github.com/CAFxX/httpcompression v0.0.9
|
||||||
github.com/cespare/xxhash/v2 v2.3.0
|
github.com/cespare/xxhash/v2 v2.3.0
|
||||||
|
@ -12,6 +12,7 @@ require (
|
||||||
github.com/go-playground/validator/v10 v10.22.1
|
github.com/go-playground/validator/v10 v10.22.1
|
||||||
github.com/golang-jwt/jwt/v5 v5.2.1
|
github.com/golang-jwt/jwt/v5 v5.2.1
|
||||||
github.com/google/uuid v1.6.0
|
github.com/google/uuid v1.6.0
|
||||||
|
github.com/klauspost/compress v1.17.11
|
||||||
github.com/lib/pq v1.10.9
|
github.com/lib/pq v1.10.9
|
||||||
github.com/mattn/go-sqlite3 v1.14.24
|
github.com/mattn/go-sqlite3 v1.14.24
|
||||||
golang.org/x/crypto v0.28.0
|
golang.org/x/crypto v0.28.0
|
||||||
|
@ -23,7 +24,6 @@ require (
|
||||||
github.com/gabriel-vasile/mimetype v1.4.6 // indirect
|
github.com/gabriel-vasile/mimetype v1.4.6 // indirect
|
||||||
github.com/go-playground/locales v0.14.1 // indirect
|
github.com/go-playground/locales v0.14.1 // indirect
|
||||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||||
github.com/klauspost/compress v1.17.11 // indirect
|
|
||||||
github.com/kr/pretty v0.1.0 // indirect
|
github.com/kr/pretty v0.1.0 // indirect
|
||||||
github.com/leodido/go-urn v1.4.0 // indirect
|
github.com/leodido/go-urn v1.4.0 // indirect
|
||||||
github.com/stretchr/testify v1.9.0 // indirect
|
github.com/stretchr/testify v1.9.0 // indirect
|
||||||
|
|
4
go.sum
4
go.sum
|
@ -1,7 +1,7 @@
|
||||||
git.ailur.dev/ailur/fg-library/v2 v2.1.1 h1:49NgKud/gJjlTPZQfrZkmx4b/IEa3ZkO/NNM8QGA3qk=
|
git.ailur.dev/ailur/fg-library/v2 v2.1.1 h1:49NgKud/gJjlTPZQfrZkmx4b/IEa3ZkO/NNM8QGA3qk=
|
||||||
git.ailur.dev/ailur/fg-library/v2 v2.1.1/go.mod h1:Il3+GZ7tClNx4/QSt3eY4tR7NdvO+Qf00J0PKkxPrl4=
|
git.ailur.dev/ailur/fg-library/v2 v2.1.1/go.mod h1:Il3+GZ7tClNx4/QSt3eY4tR7NdvO+Qf00J0PKkxPrl4=
|
||||||
git.ailur.dev/ailur/fg-nucleus-library v1.0.3 h1:C0xgfZg7bkULhh9Ci7ZoAcx4QIqxLh+QW9/ng1kKTFU=
|
git.ailur.dev/ailur/fg-nucleus-library v1.0.4 h1:eDMkZm1OgHJtO7xyrAwZx2rsv77P6pes5FXvDNhMQ5g=
|
||||||
git.ailur.dev/ailur/fg-nucleus-library v1.0.3/go.mod h1:RbBVFRwtQgYvCWoru1mC3vUJ1dMftkNbvd7hVFtREFw=
|
git.ailur.dev/ailur/fg-nucleus-library v1.0.4/go.mod h1:RbBVFRwtQgYvCWoru1mC3vUJ1dMftkNbvd7hVFtREFw=
|
||||||
git.ailur.dev/ailur/pow v1.0.2 h1:8tb6mXZdyQYjrKRW+AUmWMi5wJoHh9Ch3oRqiJr/ivs=
|
git.ailur.dev/ailur/pow v1.0.2 h1:8tb6mXZdyQYjrKRW+AUmWMi5wJoHh9Ch3oRqiJr/ivs=
|
||||||
git.ailur.dev/ailur/pow v1.0.2/go.mod h1:fjFb1z5KtF6V14HRhGWiDmmJKggO8KyAP20Lr5OJI/g=
|
git.ailur.dev/ailur/pow v1.0.2/go.mod h1:fjFb1z5KtF6V14HRhGWiDmmJKggO8KyAP20Lr5OJI/g=
|
||||||
github.com/CAFxX/httpcompression v0.0.9 h1:0ue2X8dOLEpxTm8tt+OdHcgA+gbDge0OqFQWGKSqgrg=
|
github.com/CAFxX/httpcompression v0.0.9 h1:0ue2X8dOLEpxTm8tt+OdHcgA+gbDge0OqFQWGKSqgrg=
|
||||||
|
|
|
@ -190,7 +190,6 @@ func Main(information library.ServiceInitializationInformation) {
|
||||||
adminKey := information.Configuration["adminKey"].(string)
|
adminKey := information.Configuration["adminKey"].(string)
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
serviceIDBytes, err = ServiceInformation.ServiceID.MarshalBinary()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logFunc(err.Error(), 3, information)
|
logFunc(err.Error(), 3, information)
|
||||||
}
|
}
|
||||||
|
@ -327,11 +326,7 @@ func Main(information library.ServiceInitializationInformation) {
|
||||||
if testAppIsInternalApp {
|
if testAppIsInternalApp {
|
||||||
_, err = conn.DB.Exec("INSERT INTO oauth (appId, secret, creator, name, redirectUri, scopes, keyShareUri) VALUES ('TestApp-DoNotUse', 'none', $1, 'Test App', $2, '[\"openid\", \"clientKeyShare\"]', $3)", serviceIDBytes, ensureTrailingSlash(hostName)+"testApp", ensureTrailingSlash(hostName)+"keyExchangeTester")
|
_, err = conn.DB.Exec("INSERT INTO oauth (appId, secret, creator, name, redirectUri, scopes, keyShareUri) VALUES ('TestApp-DoNotUse', 'none', $1, 'Test App', $2, '[\"openid\", \"clientKeyShare\"]', $3)", serviceIDBytes, ensureTrailingSlash(hostName)+"testApp", ensureTrailingSlash(hostName)+"keyExchangeTester")
|
||||||
} else {
|
} else {
|
||||||
testAppCreator, err := uuid.New().MarshalBinary()
|
testAppCreator := uuid.New()
|
||||||
if err != nil {
|
|
||||||
testAppIsAvailable = false
|
|
||||||
logFunc(err.Error(), 2, information)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = conn.DB.Exec("INSERT INTO oauth (appId, secret, creator, name, redirectUri, scopes, keyShareUri) VALUES ('TestApp-DoNotUse', 'none', $1, 'Test App', $2, '[\"openid\", \"clientKeyShare\"]', $3)", testAppCreator, ensureTrailingSlash(hostName)+"testApp", ensureTrailingSlash(hostName)+"keyExchangeTester")
|
_, err = conn.DB.Exec("INSERT INTO oauth (appId, secret, creator, name, redirectUri, scopes, keyShareUri) VALUES ('TestApp-DoNotUse', 'none', $1, 'Test App', $2, '[\"openid\", \"clientKeyShare\"]', $3)", testAppCreator, ensureTrailingSlash(hostName)+"testApp", ensureTrailingSlash(hostName)+"keyExchangeTester")
|
||||||
}
|
}
|
||||||
|
@ -650,7 +645,7 @@ func Main(information library.ServiceInitializationInformation) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to insert the user
|
// Try to insert the user
|
||||||
userID, err := uuid.New().MarshalBinary()
|
userID := uuid.New()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
renderJSON(500, w, map[string]interface{}{"error": "Internal server error", "code": "08"}, information)
|
renderJSON(500, w, map[string]interface{}{"error": "Internal server error", "code": "08"}, information)
|
||||||
logFunc(err.Error(), 2, information)
|
logFunc(err.Error(), 2, information)
|
||||||
|
|
|
@ -114,16 +114,13 @@ input {
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
padding: 0 10px 0 0;
|
padding: 0 10px 0 0;
|
||||||
margin: 0 0 0 10px;
|
margin: 0 0 0 10px;
|
||||||
|
background-color: var(--background);
|
||||||
}
|
}
|
||||||
|
|
||||||
.inputBox .captchaDiv .vAlign {
|
.inputBox .captchaDiv .vAlign {
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.inputBox .captchaDiv .vAlign span {
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.inputBox input {
|
.inputBox input {
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
|
||||||
"errors"
|
|
||||||
library "git.ailur.dev/ailur/fg-library/v2"
|
library "git.ailur.dev/ailur/fg-library/v2"
|
||||||
nucleusLibrary "git.ailur.dev/ailur/fg-nucleus-library"
|
nucleusLibrary "git.ailur.dev/ailur/fg-nucleus-library"
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
|
"errors"
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-playground/validator/v10"
|
"database/sql"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -27,54 +27,6 @@ var ServiceInformation = library.Service{
|
||||||
|
|
||||||
var conn library.Database
|
var conn library.Database
|
||||||
|
|
||||||
func getQuota(user uuid.UUID, information library.ServiceInitializationInformation) (int64, error) {
|
|
||||||
// Get the user's quota from the database
|
|
||||||
var quota int64
|
|
||||||
userBytes, err := user.MarshalBinary()
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
err = conn.DB.QueryRow("SELECT quota FROM quotas WHERE id = $1", userBytes).Scan("a)
|
|
||||||
if err != nil {
|
|
||||||
if errors.Is(err, sql.ErrNoRows) {
|
|
||||||
// The user has no quota set, so we'll set it to the default quota
|
|
||||||
_, err = conn.DB.Exec("INSERT INTO quotas (id, quota) VALUES ($1, $2)", userBytes, int64(information.Configuration["defaultQuota"].(float64)))
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return int64(information.Configuration["defaultQuota"].(float64)), nil
|
|
||||||
}
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return quota, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getUsed(user uuid.UUID, information library.ServiceInitializationInformation) (int64, error) {
|
|
||||||
// Check the user's used space via the filesystem
|
|
||||||
var used int64
|
|
||||||
_, err := os.Stat(filepath.Join(information.Configuration["path"].(string), user.String()))
|
|
||||||
if err != nil {
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
// The user has no files stored, so we'll set it to 0
|
|
||||||
return 0, nil
|
|
||||||
}
|
|
||||||
return 0, err
|
|
||||||
} else {
|
|
||||||
err := filepath.Walk(filepath.Join(information.Configuration["path"].(string), user.String()), func(path string, info os.FileInfo, err error) error {
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
used += info.Size()
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return used, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func logFunc(message string, messageType uint64, information library.ServiceInitializationInformation) {
|
func logFunc(message string, messageType uint64, information library.ServiceInitializationInformation) {
|
||||||
// Log the error message to the logger service
|
// Log the error message to the logger service
|
||||||
information.Outbox <- library.InterServiceMessage{
|
information.Outbox <- library.InterServiceMessage{
|
||||||
|
@ -86,343 +38,205 @@ func logFunc(message string, messageType uint64, information library.ServiceInit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func storeFile(file nucleusLibrary.File, serviceID uuid.UUID, information library.ServiceInitializationInformation) {
|
func respondError(message string, information library.ServiceInitializationInformation, myFault bool, serviceID uuid.UUID) {
|
||||||
// Create a folder for the user if it doesn't exist
|
// Respond with an error message
|
||||||
err := os.MkdirAll(filepath.Join(information.Configuration["path"].(string), file.User.String()), 0755)
|
var err uint64 = 1
|
||||||
if err != nil {
|
if myFault {
|
||||||
// First contact the logger service
|
// Log the error message to the logger service
|
||||||
logFunc(err.Error(), 2, information)
|
logFunc(message, 2, information)
|
||||||
|
err = 2
|
||||||
|
}
|
||||||
|
information.Outbox <- library.InterServiceMessage{
|
||||||
|
ServiceID: ServiceInformation.ServiceID,
|
||||||
|
ForServiceID: serviceID,
|
||||||
|
MessageType: err,
|
||||||
|
SentAt: time.Now(),
|
||||||
|
Message: errors.New(message),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Then send the error message to the requesting service
|
func checkUserExists(userID uuid.UUID) bool {
|
||||||
information.Outbox <- library.InterServiceMessage{
|
// Check if a user exists in the database
|
||||||
ServiceID: ServiceInformation.ServiceID,
|
var userCheck []byte
|
||||||
ForServiceID: serviceID,
|
err := conn.DB.QueryRow("SELECT id FROM users WHERE id = $1", userID).Scan(&userCheck)
|
||||||
MessageType: 1, // An error that's not your fault
|
if err != nil {
|
||||||
SentAt: time.Now(),
|
if errors.Is(err, sql.ErrNoRows) {
|
||||||
Message: err.Error(),
|
return false
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return uuid.Must(uuid.FromBytes(userCheck)) == userID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// addQuota can be used with a negative quota to remove quota from a user
|
||||||
|
func addQuota(information library.ServiceInitializationInformation, message library.InterServiceMessage) {
|
||||||
|
// Add more quota to a user
|
||||||
|
if checkUserExists(message.Message.(nucleusLibrary.Quota).User) {
|
||||||
|
_, err := conn.DB.Exec("UPDATE users SET quota = quota + $1 WHERE id = $2", message.Message.(nucleusLibrary.Quota).Bytes, message.Message.(nucleusLibrary.Quota).User)
|
||||||
|
if err != nil {
|
||||||
|
respondError(err.Error(), information, true, message.ServiceID)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_, err := conn.DB.Exec("INSERT INTO users (id, quota, reserved) VALUES ($1, $2, 0)", message.Message.(nucleusLibrary.Quota).User, int64(information.Configuration["defaultQuota"].(float64))+message.Message.(nucleusLibrary.Quota).Bytes)
|
||||||
|
if err != nil {
|
||||||
|
respondError(err.Error(), information, true, message.ServiceID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Check if the user has enough space to store the file
|
// And so does addReserved
|
||||||
// Get the user's used space
|
func addReserved(information library.ServiceInitializationInformation, message library.InterServiceMessage) {
|
||||||
used, err := getUsed(file.User, information)
|
// Add more reserved space to a user
|
||||||
if err != nil {
|
if checkUserExists(message.Message.(nucleusLibrary.Quota).User) {
|
||||||
// First contact the logger service
|
_, err := conn.DB.Exec("UPDATE users SET reserved = reserved + $1 WHERE id = $2", message.Message.(nucleusLibrary.Quota).Bytes, message.Message.(nucleusLibrary.Quota).User)
|
||||||
logFunc(err.Error(), 2, information)
|
if err != nil {
|
||||||
|
respondError(err.Error(), information, true, message.ServiceID)
|
||||||
// Then send the error message to the requesting service
|
}
|
||||||
information.Outbox <- library.InterServiceMessage{
|
} else {
|
||||||
ServiceID: ServiceInformation.ServiceID,
|
_, err := conn.DB.Exec("INSERT INTO users (id, quota, reserved) VALUES ($1, $2, $3)", message.Message.(nucleusLibrary.Quota).User, int64(information.Configuration["defaultQuota"].(float64)), message.Message.(nucleusLibrary.Quota).Bytes)
|
||||||
ForServiceID: serviceID,
|
if err != nil {
|
||||||
MessageType: 1, // An error that's not your fault
|
respondError(err.Error(), information, true, message.ServiceID)
|
||||||
SentAt: time.Now(),
|
|
||||||
Message: err.Error(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getQuota(userID uuid.UUID) (int64, error) {
|
||||||
|
// Get the quota for a user
|
||||||
|
var quota int64
|
||||||
|
err := conn.DB.QueryRow("SELECT quota FROM users WHERE id = $1", userID).Scan("a)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return quota, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getUsed(userID uuid.UUID, information library.ServiceInitializationInformation) (int64, error) {
|
||||||
|
// Get the used space for a user by first getting the reserved space from file storage
|
||||||
|
var used int64
|
||||||
|
err := filepath.Walk(filepath.Join(information.Configuration["path"].(string), userID.String()), func(path string, entry os.FileInfo, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
used += entry.Size()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then add the reserved space from the database
|
||||||
|
var reserved int64
|
||||||
|
err = conn.DB.QueryRow("SELECT reserved FROM users WHERE id = $1", userID).Scan(&reserved)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return used + reserved, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func modifyFile(information library.ServiceInitializationInformation, message library.InterServiceMessage) {
|
||||||
// Check if the file already exists
|
// Check if the file already exists
|
||||||
stats, err := os.Stat(filepath.Join(information.Configuration["path"].(string), file.User.String(), serviceID.String(), file.Name))
|
path := filepath.Join(information.Configuration["path"].(string), message.Message.(nucleusLibrary.File).User.String(), message.Message.(nucleusLibrary.File).Name)
|
||||||
if err == nil {
|
|
||||||
// The file already exists, subtract the old file size from the user's used space
|
_, err := os.Stat(path)
|
||||||
used -= stats.Size()
|
if os.IsNotExist(err) {
|
||||||
|
// Delete the file
|
||||||
|
err = os.Remove(path)
|
||||||
|
if err != nil {
|
||||||
|
respondError(err.Error(), information, true, message.ServiceID)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the user's quota
|
// Check if the user has enough space
|
||||||
quota, err := getQuota(file.User, information)
|
quota, err := getQuota(message.Message.(nucleusLibrary.File).User)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// First contact the logger service
|
respondError(err.Error(), information, true, message.ServiceID)
|
||||||
logFunc(err.Error(), 2, information)
|
|
||||||
|
|
||||||
// Then send the error message to the requesting service
|
|
||||||
information.Outbox <- library.InterServiceMessage{
|
|
||||||
ServiceID: ServiceInformation.ServiceID,
|
|
||||||
ForServiceID: serviceID,
|
|
||||||
MessageType: 1, // An error that's not your fault
|
|
||||||
SentAt: time.Now(),
|
|
||||||
Message: err.Error(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
used, err := getUsed(message.Message.(nucleusLibrary.File).User, information)
|
||||||
// Check if the user has enough space to store the file
|
|
||||||
if used+int64(len(file.Bytes)) > quota {
|
|
||||||
// Then send the error message to the requesting service
|
|
||||||
information.Outbox <- library.InterServiceMessage{
|
|
||||||
ServiceID: ServiceInformation.ServiceID,
|
|
||||||
ForServiceID: serviceID,
|
|
||||||
MessageType: 3, // It's the user's fault (never say that to the customer ;P)
|
|
||||||
SentAt: time.Now(),
|
|
||||||
Message: "User has exceeded their quota",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a folder within that for the service if it doesn't exist
|
|
||||||
err = os.MkdirAll(filepath.Join(information.Configuration["path"].(string), file.User.String(), serviceID.String()), 0755)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// First contact the logger service
|
respondError(err.Error(), information, true, message.ServiceID)
|
||||||
logFunc(err.Error(), 2, information)
|
}
|
||||||
|
if used+int64(len(message.Message.(nucleusLibrary.File).Bytes)) > quota {
|
||||||
// Then send the error message to the requesting service
|
respondError("insufficient storage", information, false, message.ServiceID)
|
||||||
information.Outbox <- library.InterServiceMessage{
|
return
|
||||||
ServiceID: ServiceInformation.ServiceID,
|
|
||||||
ForServiceID: serviceID,
|
|
||||||
MessageType: 1, // An error that's not your fault
|
|
||||||
SentAt: time.Now(),
|
|
||||||
Message: err.Error(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store the file
|
// Add a file to the user's storage
|
||||||
fileStream, err := os.OpenFile(filepath.Join(information.Configuration["path"].(string), file.User.String(), serviceID.String(), file.Name), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
|
file, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// First contact the logger service
|
respondError(err.Error(), information, true, message.ServiceID)
|
||||||
logFunc(err.Error(), 2, information)
|
|
||||||
|
|
||||||
// Then send the error message to the requesting service
|
|
||||||
information.Outbox <- library.InterServiceMessage{
|
|
||||||
ServiceID: ServiceInformation.ServiceID,
|
|
||||||
ForServiceID: serviceID,
|
|
||||||
MessageType: 1, // An error that's not your fault
|
|
||||||
SentAt: time.Now(),
|
|
||||||
Message: err.Error(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write the file
|
// Write the file
|
||||||
_, err = fileStream.Write(file.Bytes)
|
_, err = file.Write(message.Message.([]byte))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// First contact the logger service
|
respondError(err.Error(), information, true, message.ServiceID)
|
||||||
logFunc(err.Error(), 2, information)
|
|
||||||
|
|
||||||
// Then send the error message to the requesting service
|
|
||||||
information.Outbox <- library.InterServiceMessage{
|
|
||||||
ServiceID: ServiceInformation.ServiceID,
|
|
||||||
ForServiceID: serviceID,
|
|
||||||
MessageType: 1, // An error that's not your fault
|
|
||||||
SentAt: time.Now(),
|
|
||||||
Message: err.Error(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close the file
|
// Close the file
|
||||||
err = fileStream.Close()
|
err = file.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// First contact the logger service
|
respondError(err.Error(), information, true, message.ServiceID)
|
||||||
logFunc(err.Error(), 2, information)
|
|
||||||
|
|
||||||
// Then send the error message to the requesting service
|
|
||||||
information.Outbox <- library.InterServiceMessage{
|
|
||||||
ServiceID: ServiceInformation.ServiceID,
|
|
||||||
ForServiceID: serviceID,
|
|
||||||
MessageType: 1, // An error that's not your fault
|
|
||||||
SentAt: time.Now(),
|
|
||||||
Message: err.Error(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Report success
|
|
||||||
information.Outbox <- library.InterServiceMessage{
|
|
||||||
ServiceID: ServiceInformation.ServiceID,
|
|
||||||
ForServiceID: serviceID,
|
|
||||||
MessageType: 0, // Success
|
|
||||||
SentAt: time.Now(),
|
|
||||||
Message: nil,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func readFile(file nucleusLibrary.File, serviceID uuid.UUID, information library.ServiceInitializationInformation) {
|
func getFile(information library.ServiceInitializationInformation, message library.InterServiceMessage) {
|
||||||
|
// Check if the file exists
|
||||||
|
path := filepath.Join(information.Configuration["path"].(string), message.Message.(nucleusLibrary.File).User.String(), message.Message.(nucleusLibrary.File).Name)
|
||||||
|
|
||||||
|
_, err := os.Stat(path)
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
respondError("file not found", information, false, message.ServiceID)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Open the file
|
// Open the file
|
||||||
fileStream, err := os.Open(filepath.Join(information.Configuration["path"].(string), file.User.String(), serviceID.String(), file.Name))
|
file, err := os.Open(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// First contact the logger service
|
respondError(err.Error(), information, true, message.ServiceID)
|
||||||
logFunc(err.Error(), 2, information)
|
|
||||||
|
|
||||||
// Then send the error message to the requesting service
|
|
||||||
information.Outbox <- library.InterServiceMessage{
|
|
||||||
ServiceID: ServiceInformation.ServiceID,
|
|
||||||
ForServiceID: serviceID,
|
|
||||||
MessageType: 1, // An error that's not your fault
|
|
||||||
SentAt: time.Now(),
|
|
||||||
Message: err.Error(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the reader
|
// Respond with the file
|
||||||
|
// It's their responsibility to close the file
|
||||||
information.Outbox <- library.InterServiceMessage{
|
information.Outbox <- library.InterServiceMessage{
|
||||||
ServiceID: ServiceInformation.ServiceID,
|
ServiceID: ServiceInformation.ServiceID,
|
||||||
ForServiceID: serviceID,
|
ForServiceID: message.ServiceID,
|
||||||
MessageType: 0, // Success
|
MessageType: 1,
|
||||||
SentAt: time.Now(),
|
SentAt: time.Now(),
|
||||||
Message: fileStream,
|
Message: file,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func removeFile(file nucleusLibrary.File, serviceID uuid.UUID, information library.ServiceInitializationInformation) {
|
// processInterServiceMessages listens for incoming messages and processes them
|
||||||
// Remove the file
|
func processInterServiceMessages(information library.ServiceInitializationInformation) {
|
||||||
err := os.Remove(filepath.Join(information.Configuration["path"].(string), file.User.String(), serviceID.String(), file.Name))
|
// Listen for incoming messages
|
||||||
if err != nil {
|
for {
|
||||||
// First contact the logger service
|
message := <-information.Inbox
|
||||||
logFunc(err.Error(), 2, information)
|
switch message.MessageType {
|
||||||
|
case 1:
|
||||||
// Then send the error message to the requesting service
|
// Add quota
|
||||||
information.Outbox <- library.InterServiceMessage{
|
addQuota(information, message)
|
||||||
ServiceID: ServiceInformation.ServiceID,
|
case 2:
|
||||||
ForServiceID: serviceID,
|
// Add reserved
|
||||||
MessageType: 1, // An error that's not your fault
|
addReserved(information, message)
|
||||||
SentAt: time.Now(),
|
case 3:
|
||||||
Message: err.Error(),
|
// Modify file
|
||||||
|
modifyFile(information, message)
|
||||||
|
case 4:
|
||||||
|
// Get file
|
||||||
|
getFile(information, message)
|
||||||
|
default:
|
||||||
|
// Respond with an error message
|
||||||
|
respondError("invalid message type", information, false, message.ServiceID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Report success
|
|
||||||
information.Outbox <- library.InterServiceMessage{
|
|
||||||
ServiceID: ServiceInformation.ServiceID,
|
|
||||||
ForServiceID: serviceID,
|
|
||||||
MessageType: 0, // Success
|
|
||||||
SentAt: time.Now(),
|
|
||||||
Message: nil,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Main(information library.ServiceInitializationInformation) {
|
func Main(information library.ServiceInitializationInformation) {
|
||||||
go func() {
|
|
||||||
for {
|
|
||||||
message := <-information.Inbox
|
|
||||||
if message.ServiceID == uuid.MustParse("00000000-0000-0000-0000-000000000001") {
|
|
||||||
if message.MessageType == 1 {
|
|
||||||
// We've received an error message. This should never happen.
|
|
||||||
logFunc("Bit flip error: Error given to non-errored service. Move away from radiation or use ECC memory.", 3, information)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
switch message.MessageType {
|
|
||||||
case 0:
|
|
||||||
// Insert file
|
|
||||||
validate := validator.New()
|
|
||||||
err := validate.Struct(message.Message.(nucleusLibrary.File))
|
|
||||||
if err != nil {
|
|
||||||
information.Outbox <- library.InterServiceMessage{
|
|
||||||
ServiceID: ServiceInformation.ServiceID,
|
|
||||||
ForServiceID: message.ServiceID,
|
|
||||||
MessageType: 2, // An error that's your fault
|
|
||||||
SentAt: time.Now(),
|
|
||||||
Message: err.Error(),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Store file
|
|
||||||
storeFile(message.Message.(nucleusLibrary.File), message.ServiceID, information)
|
|
||||||
}
|
|
||||||
case 1:
|
|
||||||
// Read file
|
|
||||||
validate := validator.New()
|
|
||||||
err := validate.Struct(message.Message.(nucleusLibrary.File))
|
|
||||||
if err != nil {
|
|
||||||
information.Outbox <- library.InterServiceMessage{
|
|
||||||
ServiceID: ServiceInformation.ServiceID,
|
|
||||||
ForServiceID: message.ServiceID,
|
|
||||||
MessageType: 2, // An error that's your fault
|
|
||||||
SentAt: time.Now(),
|
|
||||||
Message: err.Error(),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Read file
|
|
||||||
readFile(message.Message.(nucleusLibrary.File), message.ServiceID, information)
|
|
||||||
}
|
|
||||||
case 2:
|
|
||||||
// Remove file
|
|
||||||
validate := validator.New()
|
|
||||||
err := validate.Struct(message.Message.(nucleusLibrary.File))
|
|
||||||
if err != nil {
|
|
||||||
information.Outbox <- library.InterServiceMessage{
|
|
||||||
ServiceID: ServiceInformation.ServiceID,
|
|
||||||
ForServiceID: message.ServiceID,
|
|
||||||
MessageType: 2, // An error that's your fault
|
|
||||||
SentAt: time.Now(),
|
|
||||||
Message: err.Error(),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Remove file
|
|
||||||
removeFile(message.Message.(nucleusLibrary.File), message.ServiceID, information)
|
|
||||||
}
|
|
||||||
case 3:
|
|
||||||
// Get quota
|
|
||||||
validate := validator.New()
|
|
||||||
err := validate.Struct(message.Message.(uuid.UUID))
|
|
||||||
if err != nil {
|
|
||||||
information.Outbox <- library.InterServiceMessage{
|
|
||||||
ServiceID: ServiceInformation.ServiceID,
|
|
||||||
ForServiceID: message.ServiceID,
|
|
||||||
MessageType: 2, // An error that's your fault
|
|
||||||
SentAt: time.Now(),
|
|
||||||
Message: err.Error(),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Get quota
|
|
||||||
quota, err := getQuota(message.Message.(uuid.UUID), information)
|
|
||||||
if err != nil {
|
|
||||||
// First contact the logger service
|
|
||||||
logFunc(err.Error(), 2, information)
|
|
||||||
|
|
||||||
// Then send the error message to the requesting service
|
|
||||||
information.Outbox <- library.InterServiceMessage{
|
|
||||||
ServiceID: ServiceInformation.ServiceID,
|
|
||||||
ForServiceID: message.ServiceID,
|
|
||||||
MessageType: 1, // An error that's not your fault
|
|
||||||
SentAt: time.Now(),
|
|
||||||
Message: err.Error(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Report success
|
|
||||||
information.Outbox <- library.InterServiceMessage{
|
|
||||||
ServiceID: ServiceInformation.ServiceID,
|
|
||||||
ForServiceID: message.ServiceID,
|
|
||||||
MessageType: 0, // Success
|
|
||||||
SentAt: time.Now(),
|
|
||||||
Message: quota,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case 4:
|
|
||||||
// Get used
|
|
||||||
validate := validator.New()
|
|
||||||
err := validate.Struct(message.Message.(uuid.UUID))
|
|
||||||
if err != nil {
|
|
||||||
information.Outbox <- library.InterServiceMessage{
|
|
||||||
ServiceID: ServiceInformation.ServiceID,
|
|
||||||
ForServiceID: message.ServiceID,
|
|
||||||
MessageType: 2, // An error that's your fault
|
|
||||||
SentAt: time.Now(),
|
|
||||||
Message: err.Error(),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Get used
|
|
||||||
used, err := getUsed(message.Message.(uuid.UUID), information)
|
|
||||||
if err != nil {
|
|
||||||
// First contact the logger service
|
|
||||||
logFunc(err.Error(), 2, information)
|
|
||||||
|
|
||||||
// Then send the error message to the requesting service
|
|
||||||
information.Outbox <- library.InterServiceMessage{
|
|
||||||
ServiceID: ServiceInformation.ServiceID,
|
|
||||||
ForServiceID: message.ServiceID,
|
|
||||||
MessageType: 1, // An error that's not your fault
|
|
||||||
SentAt: time.Now(),
|
|
||||||
Message: err.Error(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Report success
|
|
||||||
information.Outbox <- library.InterServiceMessage{
|
|
||||||
ServiceID: ServiceInformation.ServiceID,
|
|
||||||
ForServiceID: message.ServiceID,
|
|
||||||
MessageType: 0, // Success
|
|
||||||
SentAt: time.Now(),
|
|
||||||
Message: used,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
// Initiate a connection to the database
|
// Initiate a connection to the database
|
||||||
// Call service ID 1 to get the database connection information
|
// Call service ID 1 to get the database connection information
|
||||||
information.Outbox <- library.InterServiceMessage{
|
information.Outbox <- library.InterServiceMessage{
|
||||||
|
@ -441,12 +255,12 @@ func Main(information library.ServiceInitializationInformation) {
|
||||||
conn = response.Message.(library.Database)
|
conn = response.Message.(library.Database)
|
||||||
// Create the quotas table if it doesn't exist
|
// Create the quotas table if it doesn't exist
|
||||||
if conn.DBType == library.Sqlite {
|
if conn.DBType == library.Sqlite {
|
||||||
_, err := conn.DB.Exec("CREATE TABLE IF NOT EXISTS quotas (id BLOB PRIMARY KEY, quota BIGINT)")
|
_, err := conn.DB.Exec("CREATE TABLE IF NOT EXISTS quotas (id BLOB PRIMARY KEY, quota BIGINT, reserved BIGINT)")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logFunc(err.Error(), 3, information)
|
logFunc(err.Error(), 3, information)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_, err := conn.DB.Exec("CREATE TABLE IF NOT EXISTS quotas (id BYTEA PRIMARY KEY, quota BIGINT)")
|
_, err := conn.DB.Exec("CREATE TABLE IF NOT EXISTS users (id UUID PRIMARY KEY, quota BIGINT, reserved BIGINT)")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logFunc(err.Error(), 3, information)
|
logFunc(err.Error(), 3, information)
|
||||||
}
|
}
|
||||||
|
@ -456,4 +270,7 @@ func Main(information library.ServiceInitializationInformation) {
|
||||||
// Log the error message to the logger service
|
// Log the error message to the logger service
|
||||||
logFunc(response.Message.(error).Error(), 3, information)
|
logFunc(response.Message.(error).Error(), 3, information)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Listen for incoming messages
|
||||||
|
go processInterServiceMessages(information)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue