From f991ba885df87dd7351715ffc8eb8af874788655 Mon Sep 17 00:00:00 2001 From: Sebastian Mark Date: Mon, 21 Oct 2024 15:36:26 +0200 Subject: [PATCH] feat: allow restrict Pomodoro via password - introduce password flag in server command line options - update clientCommand model - add password requirement for controlling the Pomodoro timer - document password in README --- README.md | 15 ++++++---- cmd/server/main.go | 2 ++ internal/shared/state.go | 2 ++ internal/websocket/client_commands.go | 40 ++++++++++++++------------- pkg/models/client.go | 5 ++-- 5 files changed, 38 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 955b001..b04ff29 100644 --- a/README.md +++ b/README.md @@ -22,14 +22,18 @@ Both client commands (sent to the server) and server messages (sent to the clien ### Client Commands -Clients communicate with the server by sending JSON-encoded commands. Each command must include a `command` field specifying the action to perform. Here are the available commands: +Clients communicate with the server by sending JSON-encoded commands. Each command must include a `command` field specifying the action to perform and the control `password` required to manage the Pomodoro timer. The password is set by the server (see [Usage](#usage)). + +If the client sends a command with an incorrect password it will not be allowed to control the Pomodoro, but will still receive server messages (see below). By default the password is an empty string which allows everyone to control the Pomodoro. In this case, the `password` field may be omitted in the client's command. + +Here are the available commands: | Command | Action | Example Sent by Client | |----------|-------------------------------------|-----------------------------------| -| `start` | Starts a new Pomodoro session | `{"command": "start"}` | -| `pause` | Pauses the current session | `{"command": "pause"}` | -| `resume` | Resumes a paused session | `{"command": "resume"}` | -| `reset` | Stops and resets the current session| `{"command": "reset"}` | +| `start` | Starts a new Pomodoro session | `{"command": "start", "password": ""}` | +| `pause` | Pauses the current session | `{"command": "pause", "password": ""}` | +| `resume` | Resumes a paused session | `{"command": "resume", "password": ""}` | +| `reset` | Stops and resets the current session| `{"command": "reset", "password": ""}` | #### Optional Start Parameters @@ -39,6 +43,7 @@ Example: ```json { command: "start", + password: "foobar", config: { "work": 10, // Length of the work session in seconds "shortBreak": 5, // Length of the short break in seconds diff --git a/cmd/server/main.go b/cmd/server/main.go index 9ce6580..101c14d 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -14,12 +14,14 @@ func Start() { // Define CLI flags for ListenAddress and ListenPort listenAddress := flag.String("listenAddress", shared.DefaultServerConfig.ListenAddress, "IP address to listen on") listenPort := flag.Int("listenPort", shared.DefaultServerConfig.ListenPort, "Port to listen on") + password := flag.String("password", "", "Control password for pomodoro session (optional)") flag.Parse() serverConfig := models.GoTomatoServerConfig{ ListenAddress: *listenAddress, ListenPort: *listenPort, } + shared.PomodoroPassword = *password listen := fmt.Sprintf("%s:%d", serverConfig.ListenAddress, serverConfig.ListenPort) diff --git a/internal/shared/state.go b/internal/shared/state.go index 87e8759..813ddba 100644 --- a/internal/shared/state.go +++ b/internal/shared/state.go @@ -16,3 +16,5 @@ func ResetToDefault() models.ServerMessage { Paused: false, } } + +var PomodoroPassword string diff --git a/internal/websocket/client_commands.go b/internal/websocket/client_commands.go index 45fe7de..d46f451 100644 --- a/internal/websocket/client_commands.go +++ b/internal/websocket/client_commands.go @@ -30,26 +30,28 @@ func handleClientCommands(ws *websocket.Conn) { continue } - // Process the command - switch clientCommand.Command { - case "start": - if !pomodoro.IsPomodoroOngoing() { - if clientCommand.Config != shared.UnsetPomodoroConfig { - pomodoroConfig = clientCommand.Config + // Process the command if pomodoro password matches + if clientCommand.Password == shared.PomodoroPassword { + switch clientCommand.Command { + case "start": + if !pomodoro.IsPomodoroOngoing() { + if clientCommand.Config != shared.UnsetPomodoroConfig { + pomodoroConfig = clientCommand.Config + } + go pomodoro.RunPomodoro(pomodoroConfig) // Start the timer with the list of clients + } + case "stop": + if pomodoro.IsPomodoroOngoing() { + pomodoro.ResetPomodoro() // Reset Pomodoro + } + case "pause": + if pomodoro.IsPomodoroOngoing() && !pomodoro.IsPomodoroPaused() { + pomodoro.PausePomodoro() // Pause the timer + } + case "resume": + if pomodoro.IsPomodoroOngoing() && pomodoro.IsPomodoroPaused() { + pomodoro.ResumePomodoro() // Resume the timer } - go pomodoro.RunPomodoro(pomodoroConfig) // Start the timer with the list of clients - } - case "stop": - if pomodoro.IsPomodoroOngoing() { - pomodoro.ResetPomodoro() // Reset Pomodoro - } - case "pause": - if pomodoro.IsPomodoroOngoing() && !pomodoro.IsPomodoroPaused() { - pomodoro.PausePomodoro() // Pause the timer - } - case "resume": - if pomodoro.IsPomodoroOngoing() && pomodoro.IsPomodoroPaused() { - pomodoro.ResumePomodoro() // Resume the timer } } diff --git a/pkg/models/client.go b/pkg/models/client.go index 5c3c9cc..aa134de 100644 --- a/pkg/models/client.go +++ b/pkg/models/client.go @@ -8,8 +8,9 @@ import ( // ClientCommand represents a command from the client (start/stop). type ClientCommand struct { - Command string `json:"command"` - Config GoTomatoPomodoroConfig `json:"config"` + Command string `json:"command"` // comman send to the server + Password string `json:"password"` // pomodoro control password + Config GoTomatoPomodoroConfig `json:"config"` // pomodoro config } type Client struct {