feat: support password-based Matrix login
Some checks failed
Docker CI/CD / Docker Build and Push to Docker Hub (push) Has been cancelled

This update introduces the ability for the bot to use a Matrix UserID and password for authentication, in addition to the existing Access Token method. Upon the first run with UserID and password, the bot automatically converts these credentials into an Access Token, updates the configuration with this token, and removes the password for security purposes. This enhancement simplifies the initial setup process for new users by directly utilizing Matrix login credentials, aligning with common user authentication workflows and enhancing security by not storing passwords long-term.

Refactored the bot initialization process in `GPTBot.from_config` to support dynamic login method selection based on provided credentials, and implemented automatic configuration updating to reflect the newly obtained Access Token and cleaned credentials.

Minor adjustments include formatting and comment clarification for better readability and maintenance.

This change addresses the need for a more straightforward and secure authentication process for bot deployment and user experience improvement.
This commit is contained in:
Kumi 2024-04-23 18:05:50 +02:00
parent 91a028d50b
commit c7c2cbc95f
Signed by: kumi
GPG key ID: ECBCC9082395383F
3 changed files with 31 additions and 15 deletions

View file

@ -143,17 +143,23 @@ APIKey = sk-yoursecretkey
Homeserver = https://matrix.local Homeserver = https://matrix.local
# An Access Token for the user your bot runs as # An Access Token for the user your bot runs as
# Can be obtained using a request like this:
# #
# See https://www.matrix.org/docs/guides/client-server-api#login # See https://www.matrix.org/docs/guides/client-server-api#login
# for information on how to obtain this value # for information on how to obtain this value
# #
AccessToken = syt_yoursynapsetoken AccessToken = syt_yoursynapsetoken
# The Matrix user ID of the bot (@local:domain.tld) # Instead of an Access Token, you can also use a User ID and password
# Only specify this if the bot fails to figure it out by itself # to log in. Upon first run, the bot will automatically turn this into
# an Access Token and store it in the config file, and remove the
# password from the config file.
#
# This is particularly useful if you are using Pantalaimon, where this
# is the only (easy) way to generate an Access Token.
# #
# UserID = @gptbot:matrix.local # UserID = @gptbot:matrix.local
# Password = yourpassword
############################################################################### ###############################################################################
@ -164,11 +170,6 @@ AccessToken = syt_yoursynapsetoken
# #
Path = database.db Path = database.db
# Path of the Crypto Store - required to support encrypted rooms
# (not tested/supported yet)
#
CryptoStore = store.db
############################################################################### ###############################################################################
[TrackingMore] [TrackingMore]

View file

@ -40,7 +40,12 @@ def main():
config.read(args.config) config.read(args.config)
# Create bot # Create bot
bot = GPTBot.from_config(config) bot, new_config = GPTBot.from_config(config)
# Update config with new values
if new_config:
with open(args.config, "w") as configfile:
new_config.write(configfile)
# Listen for SIGTERM # Listen for SIGTERM
signal.signal(signal.SIGTERM, sigterm_handler) signal.signal(signal.SIGTERM, sigterm_handler)

View file

@ -264,12 +264,22 @@ class GPTBot:
homeserver = config["Matrix"]["Homeserver"] homeserver = config["Matrix"]["Homeserver"]
bot.matrix_client = AsyncClient(homeserver) bot.matrix_client = AsyncClient(homeserver)
bot.matrix_client.access_token = config["Matrix"]["AccessToken"]
bot.matrix_client.user_id = config["Matrix"].get("UserID")
bot.matrix_client.device_id = config["Matrix"].get("DeviceID")
# Return the new GPTBot instance if ("Password" in config["Matrix"]) and config.get("Matrix", "Password"):
return bot await bot.matrix_client.login(password=config["Matrix"]["Password"])
config["Matrix"]["AccessToken"] = bot.matrix_client.access_token
config["Matrix"]["UserID"] = bot.matrix_client.user_id
config["Matrix"]["DeviceID"] = bot.matrix_client.device_id
config["Matrix"]["Password"] = ""
else:
bot.matrix_client.access_token = config["Matrix"]["AccessToken"]
bot.matrix_client.user_id = config["Matrix"].get("UserID")
bot.matrix_client.device_id = config["Matrix"].get("DeviceID")
# Return the new GPTBot instance and the (potentially modified) config
return bot, config
async def _get_user_id(self) -> str: async def _get_user_id(self) -> str:
"""Get the user ID of the bot from the whoami endpoint. """Get the user ID of the bot from the whoami endpoint.
@ -330,7 +340,7 @@ class GPTBot:
event_type = event.source["content"]["msgtype"] event_type = event.source["content"]["msgtype"]
except KeyError: except KeyError:
self.logger.log(f"Could not process event: {event}", "debug") self.logger.log(f"Could not process event: {event}", "debug")
continue # This is most likely not a message event continue # This is most likely not a message event
if event_type.startswith("gptbot"): if event_type.startswith("gptbot"):
messages.append(event) messages.append(event)