forked from TripwireTeam/tripwire
287 lines
6.7 KiB
Go
287 lines
6.7 KiB
Go
package main
|
|
|
|
import (
|
|
"database/sql"
|
|
|
|
"github.com/google/uuid"
|
|
_ "github.com/mattn/go-sqlite3"
|
|
)
|
|
|
|
var DB *sql.DB
|
|
|
|
func initDB() error {
|
|
db, err := sql.Open("sqlite3", "./db.sqlite")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
DB = db
|
|
err = createDatabase()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func createDatabase() error {
|
|
sqlStatement := `
|
|
CREATE TABLE IF NOT EXISTS users (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
username VARCHAR(255) NOT NULL,
|
|
password VARCHAR(255) NOT NULL,
|
|
uuid VARCHAR(255) NOT NULL,
|
|
client_token VARCHAR(255) NOT NULL,
|
|
auth_token VARCHAR(255) NOT NULL,
|
|
web_token VARCHAR(255) NOT NULL,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
`
|
|
_, err := DB.Exec(sqlStatement)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func insertUser(username string, password string) error {
|
|
playeruuid := uuid.New().String()
|
|
sqlStatement := `
|
|
INSERT INTO users (username, password, uuid, client_token, auth_token, web_token) VALUES (?, ?, ?, ?, ?, ?);
|
|
`
|
|
_, err := DB.Exec(sqlStatement, username, password, playeruuid, "", "", "")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// todo: deduplicate these functions
|
|
func getAuthToken(username string, password string) (string, error) {
|
|
sqlStatement := `
|
|
SELECT auth_token FROM users WHERE username = ? AND password = ?;
|
|
`
|
|
row := DB.QueryRow(sqlStatement, username, password)
|
|
|
|
// get auth token
|
|
var authToken string
|
|
err := row.Scan(&authToken)
|
|
if err != nil {
|
|
if err != sql.ErrNoRows {
|
|
return "", err
|
|
} else {
|
|
return "", &NotFoundError{}
|
|
}
|
|
}
|
|
if authToken == "" {
|
|
// generate new authToken
|
|
authToken = uuid.New().String()
|
|
// update authToken
|
|
sqlStatement := `
|
|
UPDATE users SET auth_token = ? WHERE username = ? AND password = ?;
|
|
`
|
|
_, err := DB.Exec(sqlStatement, authToken, username, password)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
}
|
|
return authToken, nil
|
|
}
|
|
|
|
func getWebToken(username string, password string) (string, error) {
|
|
sqlStatement := `
|
|
SELECT web_token FROM users WHERE username = ? AND password = ?;
|
|
`
|
|
row := DB.QueryRow(sqlStatement, username, password)
|
|
|
|
// get web token
|
|
var webToken string
|
|
err := row.Scan(&webToken)
|
|
if err != nil {
|
|
if err != sql.ErrNoRows {
|
|
return "", err
|
|
} else {
|
|
return "", &NotFoundError{}
|
|
}
|
|
}
|
|
if webToken == "" {
|
|
// generate new webToken
|
|
webToken = uuid.New().String()
|
|
// update authToken
|
|
sqlStatement := `
|
|
UPDATE users SET web_token = ? WHERE username = ? AND password = ?;
|
|
`
|
|
_, err := DB.Exec(sqlStatement, webToken, username, password)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
}
|
|
return webToken, nil
|
|
}
|
|
|
|
// func checkClientToken(clientToken string, userName string) (string, error) {
|
|
// // assumes user is already logged in
|
|
// sqlStatement := `
|
|
// SELECT id FROM users WHERE client_token = ? AND username = ?;
|
|
// `
|
|
// var x string
|
|
// err := DB.QueryRow(sqlStatement, clientToken, userName).Scan(&x)
|
|
|
|
// // check if row exists
|
|
// if err != nil && err != sql.ErrNoRows {
|
|
// return "", err
|
|
// }
|
|
// if err == nil {
|
|
// return clientToken, nil
|
|
// } else {
|
|
// clientToken = uuid.New().String()
|
|
// sqlStatement := `
|
|
// UPDATE users SET client_token = ? WHERE username = ?;
|
|
// `
|
|
// _, err := DB.Exec(sqlStatement, clientToken, userName)
|
|
// if err != nil {
|
|
// return "", err
|
|
// }
|
|
// clearAuthToken(userName)
|
|
// return clientToken, nil
|
|
// }
|
|
// }
|
|
|
|
func checkClientToken(clientToken string, userName string) (string, error) {
|
|
// actually just stores the token instead of checking if it's valid
|
|
sqlStatement := `
|
|
UPDATE users SET client_token = ? WHERE username = ?;
|
|
`
|
|
_, err := DB.Exec(sqlStatement, clientToken, userName)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return clientToken, nil
|
|
}
|
|
|
|
// func clearAuthToken(username string) error {
|
|
// // runs when user logs out
|
|
// sqlStatement := `
|
|
// UPDATE users SET auth_token = ? WHERE username = ?;
|
|
// `
|
|
// _, err := DB.Exec(sqlStatement, "", username)
|
|
// if err != nil {
|
|
// return err
|
|
// }
|
|
// return nil
|
|
// }
|
|
|
|
// func insertAuthToken(authToken string, userName string) error {
|
|
// sqlStatement := `
|
|
// UPDATE users SET auth_token = ? WHERE username = ?;
|
|
// `
|
|
// _, err := DB.Exec(sqlStatement, authToken, userName)
|
|
// if err != nil {
|
|
// return err
|
|
// }
|
|
// return nil
|
|
// }
|
|
|
|
func resetTokens(username string, password string) error {
|
|
sqlStatement := `
|
|
UPDATE users SET web_token = "", auth_token = "" WHERE username = ? AND password = ?;
|
|
`
|
|
_, err := DB.Exec(sqlStatement, username, password)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func createUser(username string, adminToken string) (string, error) {
|
|
// check if adminToken is valid
|
|
if validateAdminToken(adminToken) {
|
|
exists, err := playerExistsByUsername(username)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
if !exists {
|
|
// shrunk so it fits into Auth Me login
|
|
password := shrinkUUID(uuid.New().String())
|
|
insertUser(username, password)
|
|
return password, nil
|
|
} else {
|
|
return "", &AlreadyExistsError{}
|
|
}
|
|
} else {
|
|
return "", &InvalidCredentialsError{}
|
|
}
|
|
}
|
|
|
|
func refreshTokens(refresh RefreshPayload) (RefreshPayload, error) {
|
|
sqlStatement := `
|
|
SELECT id FROM users WHERE auth_token = ? and client_token = ?;
|
|
`
|
|
row := DB.QueryRow(sqlStatement, refresh.AccessToken, refresh.ClientToken)
|
|
|
|
// get id
|
|
var id int
|
|
err := row.Scan(&id)
|
|
|
|
if err != nil {
|
|
return RefreshPayload{}, err
|
|
}
|
|
// generate new authToken
|
|
authToken := uuid.New().String()
|
|
// update authToken
|
|
sqlStatement = `
|
|
UPDATE users SET auth_token = ? WHERE id = ?;
|
|
`
|
|
_, err = DB.Exec(sqlStatement, authToken, id)
|
|
if err != nil {
|
|
return RefreshPayload{}, err
|
|
}
|
|
// generate new clientToken
|
|
clientToken := uuid.New().String()
|
|
// update clientToken
|
|
sqlStatement = `
|
|
UPDATE users SET client_token = ? WHERE id = ?;
|
|
`
|
|
_, err = DB.Exec(sqlStatement, clientToken, id)
|
|
if err != nil {
|
|
return RefreshPayload{}, err
|
|
}
|
|
refresh.AccessToken = authToken
|
|
refresh.ClientToken = clientToken
|
|
return refresh, nil
|
|
}
|
|
|
|
func validateTokens(authToken string, clientToken string) (bool, error) {
|
|
sqlStatement := `
|
|
SELECT id FROM users WHERE auth_token = ? and client_token = ?;
|
|
`
|
|
var x string
|
|
err := DB.QueryRow(sqlStatement, authToken, clientToken).Scan(&x)
|
|
if err != nil {
|
|
if err == sql.ErrNoRows {
|
|
return false, nil
|
|
}
|
|
return false, err
|
|
}
|
|
return true, nil
|
|
}
|
|
|
|
func invalidateTokens(authToken string, clientToken string) error {
|
|
sqlStatement := `
|
|
UPDATE users SET auth_token = ?, client_token = ? WHERE auth_token = ? and client_token = ?;
|
|
`
|
|
_, err := DB.Exec(sqlStatement, "", "", authToken, clientToken)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func invalidateTokensWithLogin(username string, password string) error {
|
|
sqlStatement := `
|
|
UPDATE users SET auth_token = ?, client_token = ? WHERE username = ? AND password = ?;
|
|
`
|
|
_, err := DB.Exec(sqlStatement, "", "", username, password)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|