unit tests
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@ -16,3 +16,5 @@
|
|||||||
# vendor/
|
# vendor/
|
||||||
.idea
|
.idea
|
||||||
secrets.json
|
secrets.json
|
||||||
|
test
|
||||||
|
secrets_test.json
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"createGiteaAccount": false,
|
"createGiteaAccount": false,
|
||||||
"port": 8080,
|
"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/go-sql-driver/mysql v1.5.0
|
||||||
github.com/golang/protobuf v1.4.3 // indirect
|
github.com/golang/protobuf v1.4.3 // indirect
|
||||||
github.com/gorilla/websocket v1.4.2 // indirect
|
github.com/gorilla/websocket v1.4.2 // indirect
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.6
|
||||||
github.com/zaddok/moodle v0.6.6
|
github.com/zaddok/moodle v0.6.6
|
||||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad
|
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad
|
||||||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777 // indirect
|
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/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 h1:zEfKbn2+PDgroKdiOzqiE8rsmLqU2uwi5PB5pBJ3TkI=
|
||||||
github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
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 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
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=
|
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) {
|
func login(w http.ResponseWriter, r *http.Request) {
|
||||||
var redirectUrl = r.FormValue("redirecturl")
|
var redirectUrl = r.FormValue("redirecturl")
|
||||||
if redirectUrl == "" {
|
if redirectUrl == "" {
|
||||||
redirectUrl = "dash"
|
redirectUrl = "/"
|
||||||
}
|
}
|
||||||
loginStruct := loginStruct{}
|
loginStruct := loginStruct{}
|
||||||
var login bool = false
|
var login bool = false
|
||||||
@ -36,7 +36,6 @@ func login(w http.ResponseWriter, r *http.Request) {
|
|||||||
cookie := http.Cookie{
|
cookie := http.Cookie{
|
||||||
Name: sessionName,
|
Name: sessionName,
|
||||||
Value: key,
|
Value: key,
|
||||||
Domain: "redstoneunion.de",
|
|
||||||
Expires: time.Now().Add(sessionTimeout),
|
Expires: time.Now().Add(sessionTimeout),
|
||||||
HttpOnly: true,
|
HttpOnly: true,
|
||||||
Secure: true,
|
Secure: true,
|
||||||
|
|||||||
26
src/main.go
26
src/main.go
@ -7,6 +7,7 @@ import (
|
|||||||
"github.com/bwmarrin/discordgo"
|
"github.com/bwmarrin/discordgo"
|
||||||
"github.com/dlclark/regexp2"
|
"github.com/dlclark/regexp2"
|
||||||
_ "github.com/go-sql-driver/mysql"
|
_ "github.com/go-sql-driver/mysql"
|
||||||
|
_ "github.com/mattn/go-sqlite3"
|
||||||
"github.com/zaddok/moodle"
|
"github.com/zaddok/moodle"
|
||||||
"html/template"
|
"html/template"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
@ -24,6 +25,7 @@ var registerTmpl *template.Template
|
|||||||
var submitTmpl *template.Template
|
var submitTmpl *template.Template
|
||||||
var loginTmpl *template.Template
|
var loginTmpl *template.Template
|
||||||
var stmtCreateAccount *sql.Stmt
|
var stmtCreateAccount *sql.Stmt
|
||||||
|
var isTest bool
|
||||||
type secrets_json struct {
|
type secrets_json struct {
|
||||||
DiscordToken string `json:"discordToken"`
|
DiscordToken string `json:"discordToken"`
|
||||||
MysqlIndentify string `json:"mysqlIndentify"`
|
MysqlIndentify string `json:"mysqlIndentify"`
|
||||||
@ -31,17 +33,22 @@ type secrets_json struct {
|
|||||||
MoodleToken string `json:"moodleToken"`
|
MoodleToken string `json:"moodleToken"`
|
||||||
GiteaToken string `json:"giteaToken"`
|
GiteaToken string `json:"giteaToken"`
|
||||||
ApiToken string `json:"apiToken"`
|
ApiToken string `json:"apiToken"`
|
||||||
|
DiscordTestUser string `json:"discordTestUser"`
|
||||||
|
DiscordTestUserEmail string `json:"discordTestUserEmail"`
|
||||||
|
DiscordTestUserPassword string `json:"discordTestUserpassword"`
|
||||||
|
DiscordBotUserId string `json:"discordBotUserId"`
|
||||||
}
|
}
|
||||||
type config_json struct {
|
type config_json struct {
|
||||||
CreateGiteaAccount bool `json:"createGiteaAccount"`
|
CreateGiteaAccount bool `json:"createGiteaAccount"`
|
||||||
Port uint16 `json:"port"`
|
Port uint16 `json:"port"`
|
||||||
RootUrl string `json:"rootUrl"`
|
RootUrl string `json:"rootUrl"`
|
||||||
|
DatabaseType string `json:"databaseType"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
var err error
|
var err error
|
||||||
var jsonfile *os.File
|
var jsonfile *os.File
|
||||||
jsonfile, err = os.Open("secrets.json")
|
jsonfile, err = os.Open("secrets" + testFilename() + ".json")
|
||||||
log(err)
|
log(err)
|
||||||
var jsondata []byte
|
var jsondata []byte
|
||||||
jsondata, err = ioutil.ReadAll(jsonfile)
|
jsondata, err = ioutil.ReadAll(jsonfile)
|
||||||
@ -49,19 +56,23 @@ func main() {
|
|||||||
err = json.Unmarshal(jsondata, &secret)
|
err = json.Unmarshal(jsondata, &secret)
|
||||||
log(err)
|
log(err)
|
||||||
jsonfile.Close()
|
jsonfile.Close()
|
||||||
jsonfile, err = os.Open("config.json")
|
jsonfile, err = os.Open("config" + testFilename() + ".json")
|
||||||
log(err)
|
log(err)
|
||||||
jsondata, err = ioutil.ReadAll(jsonfile)
|
jsondata, err = ioutil.ReadAll(jsonfile)
|
||||||
log(err)
|
log(err)
|
||||||
err = json.Unmarshal(jsondata, &config)
|
err = json.Unmarshal(jsondata, &config)
|
||||||
log(err)
|
log(err)
|
||||||
jsonfile.Close()
|
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)
|
discordgo.MakeIntent(discordgo.IntentsAll)
|
||||||
discord, err = discordgo.New("Bot " + secret.DiscordToken)
|
discord, err = discordgo.New("Bot " + secret.DiscordToken)
|
||||||
log(err)
|
log(err)
|
||||||
err = discord.Open()
|
err = discord.Open()
|
||||||
log(err)
|
log(err)
|
||||||
db, err = sql.Open("mysql", secret.MysqlIndentify)
|
db, err = sql.Open(config.DatabaseType, secret.MysqlIndentify)
|
||||||
log(err)
|
log(err)
|
||||||
_, err = db.Exec("CREATE TABLE IF NOT EXISTS account(" +
|
_, err = db.Exec("CREATE TABLE IF NOT EXISTS account(" +
|
||||||
"username varchar(40) NOT NULL, " +
|
"username varchar(40) NOT NULL, " +
|
||||||
@ -88,5 +99,14 @@ func main() {
|
|||||||
http.HandleFunc("/login", login)
|
http.HandleFunc("/login", login)
|
||||||
http.HandleFunc("/api/accountinfo", accountApi)
|
http.HandleFunc("/api/accountinfo", accountApi)
|
||||||
|
|
||||||
|
if(!isTest) {
|
||||||
http.ListenAndServe(":" + fmt.Sprint(config.Port), nil)
|
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
|
Email bool
|
||||||
DiscordUser bool
|
DiscordUser bool
|
||||||
}
|
}
|
||||||
type registertmpl struct {
|
type registerStruct struct {
|
||||||
Success bool
|
Success bool
|
||||||
WrongAccount WrongAccount
|
WrongAccount WrongAccount
|
||||||
AlreadyEsitsInDatabase struct{
|
AlreadyEsitsInDatabase struct{
|
||||||
@ -32,7 +32,7 @@ type registertmpl struct {
|
|||||||
DiscordUsername bool
|
DiscordUsername bool
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
type SubmitStruct struct {
|
type submitStruct struct {
|
||||||
Success bool
|
Success bool
|
||||||
}
|
}
|
||||||
var cacheAccounts hashmap.HashMap
|
var cacheAccounts hashmap.HashMap
|
||||||
@ -40,7 +40,7 @@ var rusername *regexp.Regexp
|
|||||||
var remail *regexp2.Regexp
|
var remail *regexp2.Regexp
|
||||||
var rpassword *regexp2.Regexp
|
var rpassword *regexp2.Regexp
|
||||||
func register(w http.ResponseWriter, r *http.Request) {
|
func register(w http.ResponseWriter, r *http.Request) {
|
||||||
registerstruct := registertmpl{}
|
registerStruct := registerStruct{}
|
||||||
if r.Method == http.MethodPost {
|
if r.Method == http.MethodPost {
|
||||||
var newAccount account
|
var newAccount account
|
||||||
var newRbuMember *discordgo.Member
|
var newRbuMember *discordgo.Member
|
||||||
@ -54,24 +54,24 @@ func register(w http.ResponseWriter, r *http.Request) {
|
|||||||
newAccount.discordUsername = split[0]
|
newAccount.discordUsername = split[0]
|
||||||
newAccount.discordTag = split[1]
|
newAccount.discordTag = split[1]
|
||||||
}
|
}
|
||||||
registerstruct.WrongAccount.Email, _ = remail.MatchString(newAccount.email)
|
registerStruct.WrongAccount.Email, _ = remail.MatchString(newAccount.email)
|
||||||
registerstruct.WrongAccount.Email = !registerstruct.WrongAccount.Email
|
registerStruct.WrongAccount.Email = !registerStruct.WrongAccount.Email
|
||||||
registerstruct.WrongAccount.User = !rusername.MatchString(newAccount.username)
|
registerStruct.WrongAccount.User = !rusername.MatchString(newAccount.username)
|
||||||
registerstruct.WrongAccount.Pass, _ = rpassword.MatchString(newAccount.password)
|
registerStruct.WrongAccount.Pass, _ = rpassword.MatchString(newAccount.password)
|
||||||
registerstruct.WrongAccount.Pass = !registerstruct.WrongAccount.Pass
|
registerStruct.WrongAccount.Pass = !registerStruct.WrongAccount.Pass
|
||||||
newRbuMember, registerstruct.WrongAccount.DiscordUser = getRbuMember(newAccount.discordUsername, newAccount.discordTag)
|
newRbuMember, registerStruct.WrongAccount.DiscordUser = getRbuMember(newAccount.discordUsername, newAccount.discordTag)
|
||||||
registerstruct.WrongAccount.DiscordUser = !registerstruct.WrongAccount.DiscordUser
|
registerStruct.WrongAccount.DiscordUser = !registerStruct.WrongAccount.DiscordUser
|
||||||
if registerstruct.WrongAccount.DiscordUser {
|
if registerStruct.WrongAccount.DiscordUser {
|
||||||
goto registerReturn
|
goto registerReturn
|
||||||
}
|
}
|
||||||
newAccount.discordId = newRbuMember.User.ID
|
newAccount.discordId = newRbuMember.User.ID
|
||||||
{
|
{
|
||||||
var username string
|
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.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.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
|
registerStruct.Success = !registerStruct.WrongAccount.User && !registerStruct.WrongAccount.Pass && !registerStruct.WrongAccount.Email && !registerStruct.WrongAccount.DiscordUser && !registerStruct.AlreadyEsitsInDatabase.DiscordUsername && !registerStruct.AlreadyEsitsInDatabase.Username
|
||||||
if !registerstruct.Success {
|
if !registerStruct.Success {
|
||||||
goto registerReturn
|
goto registerReturn
|
||||||
}
|
}
|
||||||
token, err := GenerateRandomStringURLSafe(64)
|
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 + ">")
|
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)
|
cacheAccounts.Set(token, newAccount)
|
||||||
}
|
}
|
||||||
registerReturn: runTemplate(w, registerTmpl, registerstruct)
|
registerReturn: runTemplate(w, registerTmpl, registerStruct)
|
||||||
}
|
}
|
||||||
func submit(w http.ResponseWriter, r *http.Request) {
|
func submit(w http.ResponseWriter, r *http.Request) {
|
||||||
var err error
|
var err error
|
||||||
var submitStruct SubmitStruct
|
var submitStruct submitStruct
|
||||||
token := r.FormValue("token")
|
token := r.FormValue("token")
|
||||||
var accInter interface{}
|
var accInter interface{}
|
||||||
accInter, submitStruct.Success = cacheAccounts.GetStringKey(token)
|
accInter, submitStruct.Success = cacheAccounts.GetStringKey(token)
|
||||||
|
|||||||
Reference in New Issue
Block a user