Beispiel #1
0
// Create a new *UserState that can be used for managing users.
// dbindex is the Redis database index (0 is a good default value).
// If randomseed is true, the random number generator will be seeded after generating the cookie secret (true is a good default value).
// redisHostPort is host:port for the desired Redis server (can be blank for localhost)
// Also creates a new ConnectionPool.
func NewUserState(dbindex int, randomseed bool, redisHostPort string) *UserState {
	var pool *simpleredis.ConnectionPool

	// Connnect to the default redis server if redisHostPort is empty
	if redisHostPort == "" {
		redisHostPort = defaultRedisServer
	}

	// Test connection
	if err := simpleredis.TestConnectionHost(redisHostPort); err != nil {
		log.Fatalln(err.Error())
	}

	// Aquire connection pool
	pool = simpleredis.NewConnectionPoolHost(redisHostPort)

	state := new(UserState)

	state.users = simpleredis.NewHashMap(pool, "users")
	state.users.SelectDatabase(dbindex)

	state.usernames = simpleredis.NewSet(pool, "usernames")
	state.usernames.SelectDatabase(dbindex)

	state.unconfirmed = simpleredis.NewSet(pool, "unconfirmed")
	state.unconfirmed.SelectDatabase(dbindex)

	state.pool = pool

	state.dbindex = dbindex

	// For the secure cookies
	// This must happen before the random seeding, or
	// else people will have to log in again after every server restart
	state.cookieSecret = cookie.RandomCookieFriendlyString(30)

	// Seed the random number generator
	if randomseed {
		rand.Seed(time.Now().UnixNano())
	}

	// Cookies lasts for 24 hours by default. Specified in seconds.
	state.cookieTime = cookie.DefaultCookieTime

	// Default password hashing algorithm is "bcrypt+", which is the same as
	// "bcrypt", but with backwards compatibility for checking sha256 hashes.
	state.passwordAlgorithm = "bcrypt+" // "bcrypt+", "bcrypt" or "sha256"

	if pool.Ping() != nil {
		defer pool.Close()
		log.Fatalf("Error, wrong hostname, port or password. (%s does not reply to PING)\n", redisHostPort)
	}

	return state
}
Beispiel #2
0
// Use one of the databases for the permission middleware,
// assign a name to dbName (used for the status output) and
// return a Permissions struct.
func mustAquirePermissions() pinterface.IPermissions {
	var (
		err  error
		perm pinterface.IPermissions
	)

	// If Bolt is to be used and no filename is given
	if useBolt && (boltFilename == "") {
		boltFilename = defaultBoltFilename
	}

	if boltFilename != "" {
		// New permissions middleware, using a Bolt database
		perm, err = bolt.NewWithConf(boltFilename)
		if err != nil {
			if err.Error() == "timeout" {
				tempFile, err := ioutil.TempFile("", "algernon")
				if err != nil {
					log.Fatal("Unable to find a temporary file to use:", err)
				} else {
					boltFilename = tempFile.Name() + ".db"
				}
			} else {
				log.Errorf("Could not use Bolt as database backend: %s", err)
			}
		} else {
			dbName = "Bolt (" + boltFilename + ")"
		}
		// Try the new database filename if there was a timeout
		if dbName == "" && boltFilename != defaultBoltFilename {
			perm, err = bolt.NewWithConf(boltFilename)
			if err != nil {
				if err.Error() == "timeout" {
					log.Error("The Bolt database timed out!")
				} else {
					log.Errorf("Could not use Bolt as database backend: %s", err)
				}
			} else {
				dbName = "Bolt, temporary"
			}
		}
	}
	if dbName == "" && mariadbDSN != "" {
		// New permissions middleware, using a MariaDB/MySQL database
		perm, err = mariadb.NewWithDSN(mariadbDSN, mariaDatabase)
		if err != nil {
			log.Errorf("Could not use MariaDB/MySQL as database backend: %s", err)
		} else {
			// The connection string may contain a password, so don't include it in the dbName
			dbName = "MariaDB/MySQL"
		}
	}
	if dbName == "" && mariaDatabase != "" {
		// Given a database, but not a host, connect to localhost
		// New permissions middleware, using a MariaDB/MySQL database
		perm, err = mariadb.NewWithConf("test:@127.0.0.1/" + mariaDatabase)
		if err != nil {
			if mariaDatabase != "" {
				log.Errorf("Could not use MariaDB/MySQL as database backend: %s", err)
			} else {
				log.Warnf("Could not use MariaDB/MySQL as database backend: %s", err)
			}
		} else {
			// The connection string may contain a password, so don't include it in the dbName
			dbName = "MariaDB/MySQL"
		}
	}
	if dbName == "" {
		// New permissions middleware, using a Redis database
		if err := simpleredis.TestConnectionHost(redisAddr); err != nil {
			// Only output an error when a Redis host other than the default host+port was specified
			if redisAddrSpecified {
				if singleFileMode {
					log.Warnf("Could not use Redis as database backend: %s", err)
				} else {
					log.Errorf("Could not use Redis as database backend: %s", err)
				}
			}
		} else {
			perm = redis.NewWithRedisConf(redisDBindex, redisAddr)
			dbName = "Redis"
		}
	}
	if dbName == "" && boltFilename == "" {
		boltFilename = defaultBoltFilename
		perm, err = bolt.NewWithConf(boltFilename)
		if err != nil {
			if err.Error() == "timeout" {
				tempFile, err := ioutil.TempFile("", "algernon")
				if err != nil {
					log.Fatal("Unable to find a temporary file to use:", err)
				} else {
					boltFilename = tempFile.Name() + ".db"
				}
			} else {
				log.Errorf("Could not use Bolt as database backend: %s", err)
			}
		} else {
			dbName = "Bolt (" + boltFilename + ")"
		}
		// Try the new database filename if there was a timeout
		if boltFilename != defaultBoltFilename {
			perm, err = bolt.NewWithConf(boltFilename)
			if err != nil {
				if err.Error() == "timeout" {
					log.Error("The Bolt database timed out!")
				} else {
					log.Errorf("Could not use Bolt as database backend: %s", err)
				}
			} else {
				dbName = "Bolt, temporary"
			}
		}
	}
	if dbName == "" {
		// This may typically happen if Algernon is already running
		log.Fatalln("Could not find a usable database backend.")
	}

	return perm
}