Skip to content

Commit

Permalink
Support alternate config/users.json locations
Browse files Browse the repository at this point in the history
  • Loading branch information
retrixe committed Nov 6, 2023
1 parent b5006a8 commit 1445d4c
Show file tree
Hide file tree
Showing 8 changed files with 51 additions and 34 deletions.
4 changes: 3 additions & 1 deletion README.md
Expand Up @@ -24,7 +24,9 @@ You might want to manage octyne using systemd on Linux systems, which can start

## Configuration

Octyne depends on two files in the same directory to get configuration from. Note that Octyne refers to apps as "servers" in the config and API for legacy reasons (due to originally being targeted towards web servers and Minecraft servers).
Octyne depends on two files in the current working directory to get configuration from. Note that Octyne refers to apps as "servers" in the config and API for legacy reasons (due to originally being targeted towards web servers and Minecraft servers).

The path to these files can be customised using the `--config=/path/to/config.json` and `--users=/path/to/users.json` CLI flags (if relative, resolved relative to the working directory).

### config.json

Expand Down
4 changes: 2 additions & 2 deletions auth/memory.go
Expand Up @@ -13,8 +13,8 @@ type MemoryAuthenticator struct {
}

// NewMemoryAuthenticator initializes an authenticator using memory for token storage.
func NewMemoryAuthenticator() Authenticator {
users := CreateUserStore()
func NewMemoryAuthenticator(usersJsonPath string) Authenticator {
users := CreateUserStore(usersJsonPath)
return &MemoryAuthenticator{Tokens: xsync.NewMapOf[string](), Users: users}
}

Expand Down
4 changes: 2 additions & 2 deletions auth/redis.go
Expand Up @@ -18,8 +18,8 @@ type RedisAuthenticator struct {
}

// NewRedisAuthenticator initializes an authenticator using Redis for token storage.
func NewRedisAuthenticator(url string) *RedisAuthenticator {
users := CreateUserStore()
func NewRedisAuthenticator(usersJsonPath string, url string) *RedisAuthenticator {
users := CreateUserStore(usersJsonPath)
pool := &redis.Pool{
Wait: true,
MaxIdle: 5,
Expand Down
12 changes: 6 additions & 6 deletions auth/users.go
Expand Up @@ -9,17 +9,17 @@ import (
"github.com/puzpuzpuz/xsync/v2"
)

func CreateUserStore() *xsync.MapOf[string, string] {
func CreateUserStore(usersJsonPath string) *xsync.MapOf[string, string] {
var users = xsync.NewMapOf[string]()
initialFile, updates, err := readAndWatchFile("users.json")
initialFile, updates, err := readAndWatchFile(usersJsonPath)
if err != nil {
log.Println("An error occurred while attempting to read users.json! " + err.Error())
log.Println("An error occurred while reading " + usersJsonPath + "! " + err.Error())
return users
}
var usersJson map[string]string
err = json.Unmarshal(initialFile, &usersJson)
if err != nil {
log.Println("An error occurred while attempting to parse users.json! " + err.Error())
log.Println("An error occurred while parsing " + usersJsonPath + "! " + err.Error())
return users
}
for username, password := range usersJson {
Expand All @@ -31,7 +31,7 @@ func CreateUserStore() *xsync.MapOf[string, string] {
var usersJson map[string]string
err = json.Unmarshal(newFile, &usersJson)
if err != nil {
log.Println("An error occurred while attempting to parse users.json! " + err.Error())
log.Println("An error occurred while parsing " + usersJsonPath + "! " + err.Error())
continue
}
for username, password := range usersJson {
Expand Down Expand Up @@ -64,7 +64,7 @@ func readAndWatchFile(filePath string) ([]byte, chan []byte, error) {
time.Sleep(1 * time.Second)
newFile, err := os.ReadFile(filePath)
if err != nil {
log.Println("An error occurred while attempting to read users.json! " + err.Error())
log.Println("An error occurred while reading " + filePath + "! " + err.Error())
continue
}
if string(newFile) != string(file) {
Expand Down
23 changes: 12 additions & 11 deletions connector.go
Expand Up @@ -98,9 +98,9 @@ func InitializeConnector(config *Config) *Connector {
// Create an authenticator.
var authenticator auth.Authenticator
if config.Redis.Enabled {
authenticator = auth.NewRedisAuthenticator(config.Redis.URL)
authenticator = auth.NewRedisAuthenticator(UsersJsonPath, config.Redis.URL)
} else {
authenticator = auth.NewMemoryAuthenticator()
authenticator = auth.NewMemoryAuthenticator(UsersJsonPath)
}
// Create the connector.
connector := &Connector{
Expand Down Expand Up @@ -211,6 +211,7 @@ func writeJsonStructRes(w http.ResponseWriter, resp interface{}) error {
return json.NewEncoder(w).Encode(resp)
}

// skipcq GO-R1005
func (connector *Connector) registerMiscRoutes() {
// GET /
connector.Router.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
Expand All @@ -228,9 +229,9 @@ func (connector *Connector) registerMiscRoutes() {
return
}
if r.Method == "GET" {
contents, err := os.ReadFile("config.json")
contents, err := os.ReadFile(ConfigJsonPath)
if err != nil {
log.Println("Error reading config.json when user accessed /config!", err)
log.Println("Error reading "+ConfigJsonPath+" when user accessed /config!", err)
httpError(w, "Internal Server Error!", http.StatusInternalServerError)
return
}
Expand All @@ -255,15 +256,15 @@ func (connector *Connector) registerMiscRoutes() {
httpError(w, "Invalid JSON body!", http.StatusBadRequest)
return
}
err = os.WriteFile("config.json~", []byte(strings.TrimRight(origJson, "\n")+"\n"), 0666)
err = os.WriteFile(ConfigJsonPath+"~", []byte(strings.TrimRight(origJson, "\n")+"\n"), 0666)
if err != nil {
log.Println("Error writing to config.json when user modified config!")
log.Println("Error writing to " + ConfigJsonPath + " when user modified config!")
httpError(w, "Internal Server Error!", http.StatusInternalServerError)
return
}
err = os.Rename("config.json~", "config.json")
err = os.Rename(ConfigJsonPath+"~", ConfigJsonPath)
if err != nil {
log.Println("Error writing to config.json when user modified config!")
log.Println("Error writing to " + ConfigJsonPath + " when user modified config!")
httpError(w, "Internal Server Error!", http.StatusInternalServerError)
return
}
Expand All @@ -283,7 +284,7 @@ func (connector *Connector) registerMiscRoutes() {
}
// Read the new config.
var config Config
contents, err := os.ReadFile("config.json")
contents, err := os.ReadFile(ConfigJsonPath)
if err != nil {
log.Println("An error occurred while attempting to read config! " + err.Error())
httpError(w, "An error occurred while reading config!", http.StatusInternalServerError)
Expand Down Expand Up @@ -596,9 +597,9 @@ func (connector *Connector) UpdateConfig(config *Config) {
(usingRedis && redisAuthenticator.URL != config.Redis.URL) {
replaceableAuthenticator.Engine.Close() // Bypassing ReplaceableAuthenticator mutex Lock.
if config.Redis.Enabled {
replaceableAuthenticator.Engine = auth.NewRedisAuthenticator(config.Redis.URL)
replaceableAuthenticator.Engine = auth.NewRedisAuthenticator(UsersJsonPath, config.Redis.URL)
} else {
replaceableAuthenticator.Engine = auth.NewMemoryAuthenticator()
replaceableAuthenticator.Engine = auth.NewMemoryAuthenticator(UsersJsonPath)
}
}
// Add new processes.
Expand Down
17 changes: 9 additions & 8 deletions endpoints_auth.go
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/retrixe/octyne/auth"
)

// skipcq GO-R1005
func (connector *Connector) registerAuthRoutes() {
// GET /login
type loginResponse struct {
Expand Down Expand Up @@ -146,15 +147,15 @@ func (connector *Connector) registerAuthRoutes() {
return
}
var users map[string]string
contents, err := os.ReadFile("users.json")
contents, err := os.ReadFile(UsersJsonPath)
if err != nil {
log.Println("Error reading users.json when modifying accounts!", err)
log.Println("Error reading "+UsersJsonPath+" when modifying accounts!", err)
httpError(w, "Internal Server Error!", http.StatusInternalServerError)
return
}
err = json.Unmarshal(contents, &users)
if err != nil {
log.Println("Error parsing users.json when modifying accounts!", err)
log.Println("Error parsing "+UsersJsonPath+" when modifying accounts!", err)
httpError(w, "Internal Server Error!", http.StatusInternalServerError)
return
}
Expand Down Expand Up @@ -248,19 +249,19 @@ func (connector *Connector) registerAuthRoutes() {
}
usersJson, err := json.MarshalIndent(users, "", " ")
if err != nil {
log.Println("Error serialising users.json when modifying accounts!")
log.Println("Error serialising " + UsersJsonPath + " when modifying accounts!")
httpError(w, "Internal Server Error!", http.StatusInternalServerError)
return
}
err = os.WriteFile("users.json~", []byte(string(usersJson)+"\n"), 0666)
err = os.WriteFile(UsersJsonPath+"~", []byte(string(usersJson)+"\n"), 0666)
if err != nil {
log.Println("Error writing to users.json when modifying accounts!")
log.Println("Error writing to " + UsersJsonPath + " when modifying accounts!")
httpError(w, "Internal Server Error!", http.StatusInternalServerError)
return
}
err = os.Rename("users.json~", "users.json")
err = os.Rename(UsersJsonPath+"~", UsersJsonPath)
if err != nil {
log.Println("Error writing to users.json when modifying accounts!")
log.Println("Error writing to " + UsersJsonPath + " when modifying accounts!")
httpError(w, "Internal Server Error!", http.StatusInternalServerError)
return
}
Expand Down
1 change: 1 addition & 0 deletions endpoints_files.go
Expand Up @@ -33,6 +33,7 @@ func clean(pathToClean string) string {
return filepath.FromSlash(path.Clean(pathToClean))
}

// skipcq GO-R1005
func (connector *Connector) registerFileRoutes() {
// GET /server/{id}/files?path=path
type serverFilesResponse struct {
Expand Down
20 changes: 16 additions & 4 deletions main.go
Expand Up @@ -11,6 +11,7 @@ import (
"path/filepath"
"runtime"
"strconv"
"strings"
"syscall"
"time"

Expand All @@ -28,16 +29,27 @@ func getPort(config *Config) string {
}

var info *log.Logger
var ConfigJsonPath = "config.json"
var UsersJsonPath = "users.json"

func main() {
if len(os.Args) >= 2 && (os.Args[1] == "--version" || os.Args[1] == "-v") {
println("octyne version " + OctyneVersion)
return
for _, arg := range os.Args {
if arg == "--help" || arg == "-h" {
println("Usage: " + os.Args[0] + " [--version] [--config=<path>] [--users=<path>]")
return
} else if strings.HasPrefix(arg, "--users=") {
UsersJsonPath = arg[8:]
} else if strings.HasPrefix(arg, "--config=") {
ConfigJsonPath = arg[9:]
} else if arg == "--version" || arg == "-v" {
println("octyne version " + OctyneVersion)
return
}
}

// Read config.
var config Config
contents, err := os.ReadFile("config.json")
contents, err := os.ReadFile(ConfigJsonPath)
if err != nil {
panic("An error occurred while attempting to read config! " + err.Error())
}
Expand Down

0 comments on commit 1445d4c

Please sign in to comment.