unit tests
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@ -16,3 +16,5 @@
|
||||
# vendor/
|
||||
.idea
|
||||
secrets.json
|
||||
test
|
||||
secrets_test.json
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
{
|
||||
"createGiteaAccount": false,
|
||||
"port": 8080,
|
||||
"rootUrl": "http://localhost:8080"
|
||||
"rootUrl": "http://localhost:8080",
|
||||
"databaseType": "mysql"
|
||||
}
|
||||
|
||||
6
config_test.json
Normal file
6
config_test.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"createGiteaAccount": false,
|
||||
"port": 8080,
|
||||
"rootUrl": "http://localhost:8080",
|
||||
"databaseType": "sqlite3"
|
||||
}
|
||||
1
go.mod
1
go.mod
@ -11,6 +11,7 @@ require (
|
||||
github.com/go-sql-driver/mysql v1.5.0
|
||||
github.com/golang/protobuf v1.4.3 // indirect
|
||||
github.com/gorilla/websocket v1.4.2 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.14.6
|
||||
github.com/zaddok/moodle v0.6.6
|
||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad
|
||||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777 // indirect
|
||||
|
||||
2
go.sum
2
go.sum
@ -46,6 +46,8 @@ github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0U
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/hashicorp/go-version v1.2.1 h1:zEfKbn2+PDgroKdiOzqiE8rsmLqU2uwi5PB5pBJ3TkI=
|
||||
github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg=
|
||||
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
|
||||
@ -14,7 +14,7 @@ const sessionTimeout time.Duration = 10 * 24 * time.Hour
|
||||
func login(w http.ResponseWriter, r *http.Request) {
|
||||
var redirectUrl = r.FormValue("redirecturl")
|
||||
if redirectUrl == "" {
|
||||
redirectUrl = "dash"
|
||||
redirectUrl = "/"
|
||||
}
|
||||
loginStruct := loginStruct{}
|
||||
var login bool = false
|
||||
@ -36,7 +36,6 @@ func login(w http.ResponseWriter, r *http.Request) {
|
||||
cookie := http.Cookie{
|
||||
Name: sessionName,
|
||||
Value: key,
|
||||
Domain: "redstoneunion.de",
|
||||
Expires: time.Now().Add(sessionTimeout),
|
||||
HttpOnly: true,
|
||||
Secure: true,
|
||||
|
||||
28
src/main.go
28
src/main.go
@ -7,6 +7,7 @@ import (
|
||||
"github.com/bwmarrin/discordgo"
|
||||
"github.com/dlclark/regexp2"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
"github.com/zaddok/moodle"
|
||||
"html/template"
|
||||
"io/ioutil"
|
||||
@ -24,6 +25,7 @@ var registerTmpl *template.Template
|
||||
var submitTmpl *template.Template
|
||||
var loginTmpl *template.Template
|
||||
var stmtCreateAccount *sql.Stmt
|
||||
var isTest bool
|
||||
type secrets_json struct {
|
||||
DiscordToken string `json:"discordToken"`
|
||||
MysqlIndentify string `json:"mysqlIndentify"`
|
||||
@ -31,17 +33,22 @@ type secrets_json struct {
|
||||
MoodleToken string `json:"moodleToken"`
|
||||
GiteaToken string `json:"giteaToken"`
|
||||
ApiToken string `json:"apiToken"`
|
||||
DiscordTestUser string `json:"discordTestUser"`
|
||||
DiscordTestUserEmail string `json:"discordTestUserEmail"`
|
||||
DiscordTestUserPassword string `json:"discordTestUserpassword"`
|
||||
DiscordBotUserId string `json:"discordBotUserId"`
|
||||
}
|
||||
type config_json struct {
|
||||
CreateGiteaAccount bool `json:"createGiteaAccount"`
|
||||
Port uint16 `json:"port"`
|
||||
RootUrl string `json:"rootUrl"`
|
||||
DatabaseType string `json:"databaseType"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
var err error
|
||||
var jsonfile *os.File
|
||||
jsonfile, err = os.Open("secrets.json")
|
||||
jsonfile, err = os.Open("secrets" + testFilename() + ".json")
|
||||
log(err)
|
||||
var jsondata []byte
|
||||
jsondata, err = ioutil.ReadAll(jsonfile)
|
||||
@ -49,19 +56,23 @@ func main() {
|
||||
err = json.Unmarshal(jsondata, &secret)
|
||||
log(err)
|
||||
jsonfile.Close()
|
||||
jsonfile, err = os.Open("config.json")
|
||||
jsonfile, err = os.Open("config" + testFilename() + ".json")
|
||||
log(err)
|
||||
jsondata, err = ioutil.ReadAll(jsonfile)
|
||||
log(err)
|
||||
err = json.Unmarshal(jsondata, &config)
|
||||
log(err)
|
||||
jsonfile.Close()
|
||||
if(config.DatabaseType != "mysql" && config.DatabaseType != "sqlite3") {
|
||||
fmt.Println("Unknown database type. Use mysql or sqlite3")
|
||||
os.Exit(1)
|
||||
}
|
||||
discordgo.MakeIntent(discordgo.IntentsAll)
|
||||
discord, err = discordgo.New("Bot " + secret.DiscordToken)
|
||||
log(err)
|
||||
err = discord.Open()
|
||||
log(err)
|
||||
db, err = sql.Open("mysql", secret.MysqlIndentify)
|
||||
db, err = sql.Open(config.DatabaseType, secret.MysqlIndentify)
|
||||
log(err)
|
||||
_, err = db.Exec("CREATE TABLE IF NOT EXISTS account(" +
|
||||
"username varchar(40) NOT NULL, " +
|
||||
@ -88,5 +99,14 @@ func main() {
|
||||
http.HandleFunc("/login", login)
|
||||
http.HandleFunc("/api/accountinfo", accountApi)
|
||||
|
||||
http.ListenAndServe(":" + fmt.Sprint(config.Port), nil)
|
||||
if(!isTest) {
|
||||
http.ListenAndServe(":" + fmt.Sprint(config.Port), nil)
|
||||
}
|
||||
}
|
||||
|
||||
func testFilename() string {
|
||||
if(isTest) {
|
||||
return "_test"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
92
src/main_test.go
Normal file
92
src/main_test.go
Normal file
@ -0,0 +1,92 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"bytes"
|
||||
"strings"
|
||||
"github.com/bwmarrin/discordgo"
|
||||
"github.com/dlclark/regexp2"
|
||||
"html/template"
|
||||
"io"
|
||||
)
|
||||
|
||||
var testPassword = "*#566jgjgJJf"
|
||||
var testUsername = "ausername"
|
||||
var testSession string
|
||||
|
||||
func TestOrder(test *testing.T) {
|
||||
isTest = true
|
||||
main()
|
||||
test.Run("register", testRegister)
|
||||
test.Run("submit", testSubmit)
|
||||
test.Run("login", testLogin)
|
||||
}
|
||||
|
||||
func testSetUsernamePassword(form url.Values) {
|
||||
form.Set("username", testUsername)
|
||||
form.Set("password", testPassword)
|
||||
}
|
||||
|
||||
func testForm(test *testing.T, url string, statusCode int, handler http.HandlerFunc, form url.Values) *http.Response {
|
||||
request := httptest.NewRequest("POST", url, strings.NewReader(form.Encode()))
|
||||
request.Form = form
|
||||
recorder := httptest.NewRecorder()
|
||||
handler.ServeHTTP(recorder, request)
|
||||
if recorder.Code != statusCode {
|
||||
test.Errorf("handler returned wrong status code: got %v want %v", recorder.Code, http.StatusOK)
|
||||
}
|
||||
return recorder.Result()
|
||||
}
|
||||
|
||||
func checkBodyByTemplate(test *testing.T, response *http.Response, template *template.Template, templateData interface{}) {
|
||||
var expectedResponse bytes.Buffer
|
||||
template.Execute(&expectedResponse, templateData)
|
||||
checkBody(test, response, expectedResponse.Bytes())
|
||||
}
|
||||
|
||||
func checkBody(test *testing.T, response *http.Response, expectedResponse []byte) {
|
||||
responseBody, _ := io.ReadAll(response.Body)
|
||||
if bytes.Equal(expectedResponse, responseBody) {
|
||||
test.Errorf("unexpected body:\n%v", string(responseBody))
|
||||
}
|
||||
}
|
||||
|
||||
func testRegister(test *testing.T) {
|
||||
form := url.Values{}
|
||||
testSetUsernamePassword(form)
|
||||
form.Set("email", "jffg@fv.com")
|
||||
form.Set("discordUser", secret.DiscordTestUser)
|
||||
response := testForm(test, "/register", http.StatusOK, register, form)
|
||||
checkBodyByTemplate(test, response, registerTmpl, registerStruct{Success: true})
|
||||
}
|
||||
|
||||
func testSubmit(test *testing.T) {
|
||||
discordClient, err := discordgo.New()
|
||||
log(err)
|
||||
err = discordClient.Login(secret.DiscordTestUserEmail, secret.DiscordTestUserPassword)
|
||||
log(err)
|
||||
err = discordClient.Open()
|
||||
log(err)
|
||||
channel, err := discordClient.UserChannelCreate(secret.DiscordBotUserId)
|
||||
log(err)
|
||||
msg, err := discordClient.ChannelMessages(channel.ID, 1, "", "", channel.LastMessageID)
|
||||
log(err)
|
||||
re := regexp2.MustCompile(`(?<=\?token\=)[^>]*`, 0)
|
||||
match, _ := re.FindStringMatch(msg[0].Content)
|
||||
if match == nil {
|
||||
test.Error("The submit link was not send")
|
||||
}
|
||||
form := url.Values{}
|
||||
form.Set("token", match.String())
|
||||
response := testForm(test, "/submit", http.StatusOK, submit, form)
|
||||
checkBodyByTemplate(test, response, submitTmpl, submitStruct{Success: true})
|
||||
}
|
||||
|
||||
func testLogin(test *testing.T) {
|
||||
form := url.Values{}
|
||||
testSetUsernamePassword(form)
|
||||
testForm(test, "/login", http.StatusSeeOther, login, form)
|
||||
}
|
||||
@ -24,7 +24,7 @@ type WrongAccount struct {
|
||||
Email bool
|
||||
DiscordUser bool
|
||||
}
|
||||
type registertmpl struct {
|
||||
type registerStruct struct {
|
||||
Success bool
|
||||
WrongAccount WrongAccount
|
||||
AlreadyEsitsInDatabase struct{
|
||||
@ -32,7 +32,7 @@ type registertmpl struct {
|
||||
DiscordUsername bool
|
||||
}
|
||||
}
|
||||
type SubmitStruct struct {
|
||||
type submitStruct struct {
|
||||
Success bool
|
||||
}
|
||||
var cacheAccounts hashmap.HashMap
|
||||
@ -40,7 +40,7 @@ var rusername *regexp.Regexp
|
||||
var remail *regexp2.Regexp
|
||||
var rpassword *regexp2.Regexp
|
||||
func register(w http.ResponseWriter, r *http.Request) {
|
||||
registerstruct := registertmpl{}
|
||||
registerStruct := registerStruct{}
|
||||
if r.Method == http.MethodPost {
|
||||
var newAccount account
|
||||
var newRbuMember *discordgo.Member
|
||||
@ -54,24 +54,24 @@ func register(w http.ResponseWriter, r *http.Request) {
|
||||
newAccount.discordUsername = split[0]
|
||||
newAccount.discordTag = split[1]
|
||||
}
|
||||
registerstruct.WrongAccount.Email, _ = remail.MatchString(newAccount.email)
|
||||
registerstruct.WrongAccount.Email = !registerstruct.WrongAccount.Email
|
||||
registerstruct.WrongAccount.User = !rusername.MatchString(newAccount.username)
|
||||
registerstruct.WrongAccount.Pass, _ = rpassword.MatchString(newAccount.password)
|
||||
registerstruct.WrongAccount.Pass = !registerstruct.WrongAccount.Pass
|
||||
newRbuMember, registerstruct.WrongAccount.DiscordUser = getRbuMember(newAccount.discordUsername, newAccount.discordTag)
|
||||
registerstruct.WrongAccount.DiscordUser = !registerstruct.WrongAccount.DiscordUser
|
||||
if registerstruct.WrongAccount.DiscordUser {
|
||||
registerStruct.WrongAccount.Email, _ = remail.MatchString(newAccount.email)
|
||||
registerStruct.WrongAccount.Email = !registerStruct.WrongAccount.Email
|
||||
registerStruct.WrongAccount.User = !rusername.MatchString(newAccount.username)
|
||||
registerStruct.WrongAccount.Pass, _ = rpassword.MatchString(newAccount.password)
|
||||
registerStruct.WrongAccount.Pass = !registerStruct.WrongAccount.Pass
|
||||
newRbuMember, registerStruct.WrongAccount.DiscordUser = getRbuMember(newAccount.discordUsername, newAccount.discordTag)
|
||||
registerStruct.WrongAccount.DiscordUser = !registerStruct.WrongAccount.DiscordUser
|
||||
if registerStruct.WrongAccount.DiscordUser {
|
||||
goto registerReturn
|
||||
}
|
||||
newAccount.discordId = newRbuMember.User.ID
|
||||
{
|
||||
var username string
|
||||
registerstruct.AlreadyEsitsInDatabase.Username = db.QueryRow("SELECT username FROM account WHERE username = ?", newAccount.username).Scan(&username) == nil || UsernameExistsInMem(newAccount.username) // check if username exits
|
||||
registerstruct.AlreadyEsitsInDatabase.DiscordUsername = db.QueryRow("SELECT username FROM account WHERE discordUserId = ?", newAccount.discordId).Scan(&username) == nil || discordUsernameExistsInMem(newAccount.discordId)
|
||||
registerStruct.AlreadyEsitsInDatabase.Username = db.QueryRow("SELECT username FROM account WHERE username = ?", newAccount.username).Scan(&username) == nil || UsernameExistsInMem(newAccount.username) // check if username exits
|
||||
registerStruct.AlreadyEsitsInDatabase.DiscordUsername = db.QueryRow("SELECT username FROM account WHERE discordUserId = ?", newAccount.discordId).Scan(&username) == nil || discordUsernameExistsInMem(newAccount.discordId)
|
||||
}
|
||||
registerstruct.Success = !registerstruct.WrongAccount.User && !registerstruct.WrongAccount.Pass && !registerstruct.WrongAccount.Email && !registerstruct.WrongAccount.DiscordUser && !registerstruct.AlreadyEsitsInDatabase.DiscordUsername && !registerstruct.AlreadyEsitsInDatabase.Username
|
||||
if !registerstruct.Success {
|
||||
registerStruct.Success = !registerStruct.WrongAccount.User && !registerStruct.WrongAccount.Pass && !registerStruct.WrongAccount.Email && !registerStruct.WrongAccount.DiscordUser && !registerStruct.AlreadyEsitsInDatabase.DiscordUsername && !registerStruct.AlreadyEsitsInDatabase.Username
|
||||
if !registerStruct.Success {
|
||||
goto registerReturn
|
||||
}
|
||||
token, err := GenerateRandomStringURLSafe(64)
|
||||
@ -82,11 +82,11 @@ func register(w http.ResponseWriter, r *http.Request) {
|
||||
discord.ChannelMessageSend(dmChannel.ID, "Bitte klicke auf den Link, um die Erstellung des Accounts abzuschließen.\n<" + config.RootUrl + "/submit?token=" + token + ">")
|
||||
cacheAccounts.Set(token, newAccount)
|
||||
}
|
||||
registerReturn: runTemplate(w, registerTmpl, registerstruct)
|
||||
registerReturn: runTemplate(w, registerTmpl, registerStruct)
|
||||
}
|
||||
func submit(w http.ResponseWriter, r *http.Request) {
|
||||
var err error
|
||||
var submitStruct SubmitStruct
|
||||
var submitStruct submitStruct
|
||||
token := r.FormValue("token")
|
||||
var accInter interface{}
|
||||
accInter, submitStruct.Success = cacheAccounts.GetStringKey(token)
|
||||
|
||||
Reference in New Issue
Block a user