|
@@ -1,9 +1,15 @@
|
|
|
package authlogger
|
|
|
|
|
|
import (
|
|
|
+ "encoding/json"
|
|
|
+ "errors"
|
|
|
"log"
|
|
|
"net/http"
|
|
|
+ "strconv"
|
|
|
+ "strings"
|
|
|
"time"
|
|
|
+
|
|
|
+ "imuslab.com/arozos/mod/database"
|
|
|
)
|
|
|
|
|
|
/*
|
|
@@ -16,16 +22,111 @@ import (
|
|
|
*/
|
|
|
|
|
|
type Logger struct {
|
|
|
+ database *database.Database
|
|
|
+}
|
|
|
+
|
|
|
+type LoginRecord struct {
|
|
|
+ Timestamp int64
|
|
|
+ TargetUsername string
|
|
|
+ LoginSucceed bool
|
|
|
+ IpAddr string
|
|
|
+ Port int
|
|
|
}
|
|
|
|
|
|
//New Logger create a new logger object
|
|
|
-func NewLogger() *Logger {
|
|
|
- return &Logger{}
|
|
|
+func NewLogger() (*Logger, error) {
|
|
|
+ db, err := database.NewDatabase("./system/auth/authlog.db", false)
|
|
|
+ if err != nil {
|
|
|
+ return nil, errors.New("*ERROR* Failed to create database for login tracking")
|
|
|
+ }
|
|
|
+ return &Logger{
|
|
|
+ database: db,
|
|
|
+ }, nil
|
|
|
}
|
|
|
|
|
|
//Log the current authentication to record, Require the request object and login status
|
|
|
-func (l *Logger) LogAuth(r *http.Request, loginStatus bool) {
|
|
|
+func (l *Logger) LogAuth(r *http.Request, loginStatus bool) error {
|
|
|
username, _ := mv(r, "username", true)
|
|
|
timestamp := time.Now().Unix()
|
|
|
- log.Println("Logger log (timestamp, username, login succeed)", timestamp, username, loginStatus)
|
|
|
+
|
|
|
+ //Get the current month as the table name, create table if not exists
|
|
|
+ current := time.Now().UTC()
|
|
|
+ tableName := current.Format("Jan-2006")
|
|
|
+
|
|
|
+ //Create table if not exists
|
|
|
+ l.database.NewTable(tableName)
|
|
|
+
|
|
|
+ //Split the remote address into ipaddr and port
|
|
|
+ remoteAddrInfo := strings.Split(r.RemoteAddr, ":")
|
|
|
+ port := -1
|
|
|
+ if len(remoteAddrInfo) > 1 {
|
|
|
+ port, _ = strconv.Atoi(remoteAddrInfo[1])
|
|
|
+ }
|
|
|
+
|
|
|
+ //Create the entry log struct
|
|
|
+ thisRecord := LoginRecord{
|
|
|
+ Timestamp: timestamp,
|
|
|
+ TargetUsername: username,
|
|
|
+ LoginSucceed: loginStatus,
|
|
|
+ IpAddr: remoteAddrInfo[0],
|
|
|
+ Port: port,
|
|
|
+ }
|
|
|
+ //Write the log to it
|
|
|
+ entryKey := strconv.Itoa(int(time.Now().UnixNano()))
|
|
|
+ err := l.database.Write(tableName, entryKey, thisRecord)
|
|
|
+ if err != nil {
|
|
|
+ log.Println("*ERROR* Failed to write authentication log. Is the storage fulled?")
|
|
|
+ log.Println(err.Error())
|
|
|
+ return err
|
|
|
+ }
|
|
|
+
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+//Close the database when system shutdown
|
|
|
+func (l *Logger) Close() {
|
|
|
+ l.database.Close()
|
|
|
+}
|
|
|
+
|
|
|
+//List the total number of months recorded in the database
|
|
|
+func (l *Logger) ListSummary() []string {
|
|
|
+ tableNames := []string{}
|
|
|
+ l.database.Tables.Range(func(tableName, _ interface{}) bool {
|
|
|
+ tableNames = append(tableNames, tableName.(string))
|
|
|
+ return true
|
|
|
+ })
|
|
|
+
|
|
|
+ return tableNames
|
|
|
+}
|
|
|
+
|
|
|
+func (l *Logger) ListRecords(key string) ([]LoginRecord, error) {
|
|
|
+ results := []LoginRecord{}
|
|
|
+ if l.database.TableExists(key) {
|
|
|
+ //Read all record from the database to login records
|
|
|
+ entries, err := l.database.ListTable(key)
|
|
|
+ if err != nil {
|
|
|
+ return results, err
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, keypairs := range entries {
|
|
|
+ record := LoginRecord{}
|
|
|
+ json.Unmarshal(keypairs[1], &record)
|
|
|
+ results = append(results, record)
|
|
|
+ }
|
|
|
+
|
|
|
+ return results, nil
|
|
|
+ } else {
|
|
|
+ return results, errors.New("Table not exists")
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+//Extract the address information from the request object, the first one is the remote address from the last hop,
|
|
|
+//and the 2nd one is the source address filled in by the client (not accurate)
|
|
|
+func getIpAddressFromRequest(r *http.Request) (string, []string) {
|
|
|
+ lastHopAddress := r.RemoteAddr
|
|
|
+ possibleSourceAddress := []string{}
|
|
|
+ rawHeader := r.Header.Get("X-Forwarded-For")
|
|
|
+ possibleSourceAddress = strings.Split(rawHeader, ", ")
|
|
|
+
|
|
|
+ return lastHopAddress, possibleSourceAddress
|
|
|
}
|