diff --git a/CODE-OF-CONDUCT.md b/CODE-OF-CONDUCT.md index a9601a6..b7be330 100644 --- a/CODE-OF-CONDUCT.md +++ b/CODE-OF-CONDUCT.md @@ -37,7 +37,7 @@ Automated agents, bots, or autonomous AI systems _may not_ independently submit Contributors may use software tools, including AI-assisted tools, but the submitting contributor _must:_ - Fully understand the contribution. -- Be able to explain design and implementation decisions. +- Be able to explain design and implementation decisions without the use of AI. - Accept responsibility for maintenance and correctness. Project maintainers retain _full discretion_ to accept or reject contributions for any reason consistent with the project's goals, diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..46b749a --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,29 @@ +# Contribution Guidelines for Amsterdam + +## Introduction + +This document explains how to contribute changes to the Amsterdam project. + +## Development Location + +While you may have found this project on GitHub or another site, the "source of truth" for the project will always +reside on [the Erbosoft code hosting site](https://git.erbosoft.com/amy/amsterdam). Serious contributors should +contact [Amy Bowersox](https://links.inclusiveladyship.com/@amy) for access. + +## AI Contribution Policy + +As per our [Code of Conduct](CODE-OF-CONDUCT.md), AI contributions are acceptable, but the submitting contributor _must:_ +* Fully understand the contribution. +* Be able to explain design and implementation decisions without the use of AI. +* Accept responsibility for maintenance and correctness. + +Contributors should indicate AI-generated content in issue and pull request descriptions and comments, specifying which model was used. + +Do _not_ use AI to reply to questions about your issue or pull request. The questions are for _you,_ the human, not an AI model. + +All project contributions must be submitted by _identifiable human participants_ who accept full responibility for their content. +Automated agents, bots, or autonomous AI systems _may not_ independently submit issues, pull requests, or other contributions. + +Project maintainers retain _full discretion_ to close pull requests and issues that appear to be low-quality AI-generated content. +While we welcome new contributors, we want to see those that will engage constructively with the review process, rather than deferring +to AI. diff --git a/MAINTAINERS b/MAINTAINERS new file mode 100644 index 0000000..032fae1 --- /dev/null +++ b/MAINTAINERS @@ -0,0 +1 @@ +Amy G. Bowersox (amysox) diff --git a/README.md b/README.md index 358297a..492e2d4 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,7 @@ You will need a MySQL database to store Amsterdam data. Create a new empty datab MySQL server, use that.) Ensure a user in your database is granted SELECT, INSERT, UPDATE, and DELETE privileges to all tables in your new database. +This is the user that you will configure Amsterdam to use. The database may be specified to Amsterdam with the following command line options or environment variables: @@ -84,3 +85,45 @@ Amsterdam also requires access to a local SMTP server, as it sends out E-mail me password reminders, subscribed posts, and messages from conference or community hosts. It may be specified to Amsterdam with the following command line options or environment variables: +* Host name: Command line options `-m` or `--mail-host`, or environment variable `AMSTERDAM_MAIL_HOST` +* Port number: Command line options `-o` or `--mail-port`, or environment variable `AMSTERDAM_MAIL_PORT` +* TLS option ("none" or "starttls"): `-S` or `--mail-tls`, or environment variable `AMSTERDAM_MAIL_TLS` +* Authentication type ("none" or "plain"): `-a` or `--mail-authtype`, or environment variable `AMSTERDAM_MAIL_AUTHTYPE` +* User name: Command line options `-U` or `--mail-user`, or environment variable `AMSTERDAM_MAIL_USER` +* Password: Command line options `-W` or `--mail-password`, or environment variable `AMSTERDAM_MAIL_PASSWORD` + +All these options may also be specified via the configuration file (see below). + +By default, Amsterdam sends log messages to stdout. You can change the log level for Amsterdam with the `-L` or `--level` +options on the command line, or the `AMSTERDAM_LOG_LEVEL` environment variable. Valid values are "trace" (most detailed), +"debug", "info", "warn", "error", "fatal", and "panic" (least detailed). + +Connect to Amsterdam on port 1323 by default. You can change this with the `-l` or `--listen` options on the +command line, or with the `AMSTERDAM_LISTEN` environment variable. Listening addresses are specified as "host:port", +or just ":port" to listen on all interfaces. + +By default, Amsterdam runs in debug mode. You can put it in "production" mode by using the `-P` or `--production` +options on the command line, or by setting the `AMSTERDAM_PROD` environment variable. + +### The Amsterdam Configuration File + +At startup, Amsterdam looks for the configuration file `amsterdam.yaml` in various directories by host OS: + +* Unix/Linux: `/usr/local/etc/amsterdam`, `/etc/amsterdam`, `/etc/xdg/amsterdam` +* macOS: `/usr/local/etc/amsterdam`, `/Library/Application Support/Amsterdam` +* Windows: `%PROGRAMDATA%\amsterdam` + +You can also specify Amsterdam's configuration file by using the `-C` or `--config` options on the command line, +or with the `AMSTERDAM_CONFIG` environment variable. + +The exact format of the configuration file is shown in the `config/default.yaml` file. When creating an Amsterdam +configuration file, you do not have to specify options for which you do not with to change the default. + +## Contributing + +See the [Contributors' Guide](CONTRIBUTING.md) for details. + +## License + +This project is licensed under [the Mozilla Public License, Version 2.0](LICENSE.md). + diff --git a/config/config.go b/config/config.go index 4e20245..fa1b0fe 100644 --- a/config/config.go +++ b/config/config.go @@ -45,8 +45,14 @@ type AmCLI struct { Debug bool `arg:"-D,--debug,env:AMSTERDAM_DEBUG" help:"Force Amsterdam to run in debug mode."` LogLevel string `arg:"-L,--level,--loglevel,env:AMSTERDAM_LOG_LEVEL" help:"Set the log level for the server."` Production bool `arg:"-P,--production,env:AMSTERDAM_PROD" help:"Force Amsterdam to run in production mode."` + MailTLS string `arg:"-S,--mail-tls,env:AMSTERDAM_MAIL_TLS" help:"The TLS setting for mail connections ('none' or 'starttls')"` + MailUser string `arg:"-U,--mail-user,env:AMSTERDAM_MAIL_USER" help:"User name to use with the mail server"` + MailPassword string `arg:"-W,--mail-password,env:AMSTERDAM_MAIL_PASSWORD" help:"Password to use with the mail server"` + MailAuthType string `arg:"-a,--mail-authtype,env:AMSTERDAM_MAIL_AUTHTYPE" help:"The SMTP authentication type ('none' or 'plain')"` DatabaseName string `arg:"-d,--database-name,env:AMSTERDAM_DATABASE_NAME" help:"Database name to use on the database server."` Listen string `arg:"-l,--listen,env:AMSTERDAM_LISTEN" help:"The local address and port for Amsterdam to listen on."` + MailHost string `arg:"-m,--mail-host,env:AMSTERDAM_MAIL_HOST" help:"The SMTP mail host to use to send messages."` + MailPort int `arg:"-o,--mail-port,env:AMSTERDAM_MAIL_PORT" help:"The SMTP port to connect to."` DatabasePassword string `arg:"-p,--database-password,env:AMSTERDAM_DATABASE_PASSWORD" help:"Password for the database server."` DatabaseHost string `arg:"-t,--database-host,env:AMSTERDAM_DATABASE_HOST" help:"Hostname for the database server."` DatabaseUser string `arg:"-u,--database-user,env:AMSTERDAM_DATABASE_USER" help:"User name for the database server."` @@ -201,6 +207,12 @@ type AmConfigComputed struct { DatabaseUser string // user name for database DatabasePassword string // password for database DatabaseName string // database name + MailHost string // SMTP host + MailPort int // SMTP port + MailTLS string // SMTP TLS setting + MailAuthType string // SMTP auth type + MailUser string // SMTP user name + MailPassword string // SMTP password UploadMaxSize int32 // maximum upload size in bytes UploadNoCompress map[string]bool // which upload types are not compressed? } @@ -377,6 +389,12 @@ func SetupConfig() { GlobalComputedConfig.DatabaseUser = util.IIF(CommandLine.DatabaseUser != "", CommandLine.DatabaseUser, GlobalConfig.Database.User) GlobalComputedConfig.DatabasePassword = util.IIF(CommandLine.DatabasePassword != "", CommandLine.DatabasePassword, GlobalConfig.Database.Password) GlobalComputedConfig.DatabaseName = util.IIF(CommandLine.DatabaseName != "", CommandLine.DatabaseName, GlobalConfig.Database.DatabaseName) + GlobalComputedConfig.MailHost = util.IIF(CommandLine.MailHost != "", CommandLine.MailHost, GlobalConfig.Email.Host) + GlobalComputedConfig.MailPort = util.IIF(CommandLine.MailPort != 0, CommandLine.MailPort, GlobalConfig.Email.Port) + GlobalComputedConfig.MailTLS = util.IIF(CommandLine.MailTLS != "", CommandLine.MailTLS, GlobalConfig.Email.Tls) + GlobalComputedConfig.MailAuthType = util.IIF(CommandLine.MailAuthType != "", CommandLine.MailAuthType, GlobalConfig.Email.AuthType) + GlobalComputedConfig.MailUser = util.IIF(CommandLine.MailUser != "", CommandLine.MailUser, GlobalConfig.Email.User) + GlobalComputedConfig.MailPassword = util.IIF(CommandLine.MailPassword != "", CommandLine.MailPassword, GlobalConfig.Email.Password) tmp, err := humanize.ParseBytes(GlobalConfig.Posting.Uploads.MaxSize) if err != nil { panic(err.Error()) diff --git a/email/sender.go b/email/sender.go index 71b524d..7522ff0 100644 --- a/email/sender.go +++ b/email/sender.go @@ -119,7 +119,7 @@ func transmitMessage(m *amMessage, body []byte) { defer cl.Close() me, _ := os.Hostname() if err = cl.Hello(me); err == nil { - if config.GlobalConfig.Email.Tls == "starttls" { + if config.GlobalComputedConfig.MailTLS == "starttls" { if ok, _ := cl.Extension("STARTTLS"); ok { err = cl.StartTLS(nil) } else { @@ -195,15 +195,15 @@ var sendChan chan *amMessage // SetupMailSender starts the mail-sending goroutine. func SetupMailSender() func() { // Initialize mail host and authentication. - mailHost = fmt.Sprintf("%s:%d", config.GlobalConfig.Email.Host, config.GlobalConfig.Email.Port) - switch config.GlobalConfig.Email.AuthType { + mailHost = fmt.Sprintf("%s:%d", config.GlobalComputedConfig.MailHost, config.GlobalComputedConfig.MailPort) + switch config.GlobalComputedConfig.MailAuthType { case "none": auth = nil case "plain": - auth = smtp.PlainAuth("", config.GlobalConfig.Email.User, config.GlobalConfig.Email.Password, - config.GlobalConfig.Email.Host) + auth = smtp.PlainAuth("", config.GlobalComputedConfig.MailUser, config.GlobalComputedConfig.MailPassword, + config.GlobalComputedConfig.MailHost) default: - panic("Unknown auth type: " + config.GlobalConfig.Email.AuthType) + panic("Unknown auth type: " + config.GlobalComputedConfig.MailAuthType) } // Split the configured disclaimer and signature.