diff --git a/RBU_account b/RBU_account new file mode 100755 index 0000000..597f080 Binary files /dev/null and b/RBU_account differ diff --git a/config.json b/config.json new file mode 100644 index 0000000..e990eb9 --- /dev/null +++ b/config.json @@ -0,0 +1,3 @@ +{ + "createGiteaAccount": false +} diff --git a/go.mod b/go.mod index 50fcedb..78ab2e3 100644 --- a/go.mod +++ b/go.mod @@ -3,12 +3,14 @@ module git.redstoneunion.de/MrGeorgen/RBU_account go 1.14 require ( + code.gitea.io/sdk/gitea v0.13.1 github.com/bwmarrin/discordgo v0.22.0 github.com/cornelk/hashmap v1.0.1 github.com/dlclark/regexp2 v1.4.0 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/hashicorp/go-version v1.2.1 // indirect github.com/tidwall/rhh v1.1.1 // indirect github.com/tidwall/shardmap v0.0.0-20190927132224-c190691bd211 github.com/zaddok/moodle v0.6.6 diff --git a/go.sum b/go.sum index 200c74d..6abe670 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,7 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +code.gitea.io/sdk v0.11.0 h1:R3VdjBCxObyLKnv4Svd/TM6oGsXzN8JORbzgkEFb83w= +code.gitea.io/sdk/gitea v0.13.1 h1:Y7bpH2iO6Q0KhhMJfjP/LZ0AmiYITeRQlCD8b0oYqhk= +code.gitea.io/sdk/gitea v0.13.1/go.mod h1:z3uwDV/b9Ls47NGukYM9XhnHtqPh/J+t40lsUrR6JDY= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/bwmarrin/discordgo v0.20.3 h1:AxjcHGbyBFSC0a3Zx5nDQwbOjU7xai5dXjRnZ0YB7nU= @@ -11,6 +14,7 @@ github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghf github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cornelk/hashmap v1.0.1 h1:RXGcy29hEdLLV8T6aK4s+BAd4tq4+3Hq50N2GoG0uIg= github.com/cornelk/hashmap v1.0.1/go.mod h1:8wbysTUDnwJGrPZ1Iwsou3m+An6sldFrJItjRhfegCw= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dchest/siphash v1.1.0 h1:1Rs9eTUlZLPBEvV+2sTaM8O0NWn0ppbgqS7p11aWawI= github.com/dchest/siphash v1.1.0/go.mod h1:q+IRvb2gOSrUnYoPqHiyHXS0FOBBOdl6tONBlVnOnt4= github.com/dlclark/regexp2 v1.2.0 h1:8sAhBGEM0dRWogWqWyQeIJnxjWO6oIjl8FKqREDsGfk= @@ -44,8 +48,15 @@ github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/hashicorp/go-version v1.2.0 h1:3vNe/fWF5CBgRIguda1meWhsZHy3m8gCJ5wx+dIzX/E= +github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +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/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/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/tidwall/lotsa v1.0.1/go.mod h1:X6NiU+4yHA3fE3Puvpnn1XMDrFZrE9JO2/w+UMuqgR8= github.com/tidwall/rhh v1.1.1 h1:8zDpMKcK1pA1zU+Jyuo1UdzTFvME8pH3Sx/MdYgM5sE= github.com/tidwall/rhh v1.1.1/go.mod h1:DmqiIRtSnlVEi5CSKqNaX6m3YTa3YNSYrGB4FlfdLUU= @@ -123,5 +134,7 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/src/main.go b/src/main.go index 64fa8d9..c492860 100644 --- a/src/main.go +++ b/src/main.go @@ -13,7 +13,6 @@ import ( "net/http" "os" "regexp" - "strings" "golang.org/x/crypto/argon2" "context" "time" @@ -26,6 +25,7 @@ var config config_json var cacheAccounts hashmap.HashMap var db *sql.DB var giteaClient *gitea.Client +var registerTmpl *template.Template type account struct { email string username string @@ -98,57 +98,12 @@ func main() { log(err) moodle := moodle.NewMoodleApi("https://exam.redstoneunion.de/", secret.MoodleToken) _ = moodle - tmpl := template.Must(template.ParseFiles("tmpl/register.html")) + registerTmpl = template.Must(template.ParseFiles("tmpl/register.html")) submitTmpl := template.Must(template.ParseFiles("tmpl/submit.html")) - remail := regexp2.MustCompile("^(?=.{0,255}$)(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])$", 0) - rusername := regexp.MustCompile("^([[:lower:]]|\\d|_|-|\\.){1,40}$") - rpassword := regexp2.MustCompile("^(?=.{8,255}$)(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*\\W).*$", 0) - http.HandleFunc("/register", func(w http.ResponseWriter, r *http.Request) { - registerstruct := registertmpl{} - if r.Method == http.MethodPost { - var newAccount account - var newRbuMember *discordgo.Member - var split = strings.Split(r.FormValue("discordUser"), "#") - newAccount = account{ - email: r.FormValue("email"), - username: r.FormValue("username"), - password: r.FormValue("password"), - } - if len(split) == 2 { - 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 { - 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.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) - log(err) - var dmChannel *discordgo.Channel - dmChannel, err = discord.UserChannelCreate(newRbuMember.User.ID) - log(err) - discord.ChannelMessageSend(dmChannel.ID, "Bitte klicke auf den Link, um die Erstellung des Accounts abzuschließen.\nhttp://localhost:8080/submit?token=" + token) - cacheAccounts.Set(token, newAccount) - } - registerReturn: err = tmpl.Execute(w, registerstruct) - log(err) - }) + remail = regexp2.MustCompile("^(?=.{0,255}$)(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])$", 0) + rusername = regexp.MustCompile("^([[:lower:]]|\\d|_|-|\\.){1,40}$") + rpassword = regexp2.MustCompile("^(?=.{8,255}$)(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*\\W).*$", 0) + http.HandleFunc("/register", register) http.HandleFunc("/submit", func(w http.ResponseWriter, r *http.Request) { var submitStruct SubmitStruct token := r.FormValue("token") diff --git a/src/register.go b/src/register.go new file mode 100644 index 0000000..a99f952 --- /dev/null +++ b/src/register.go @@ -0,0 +1,59 @@ +package main +import ( + "github.com/bwmarrin/discordgo" + _ "github.com/go-sql-driver/mysql" + "net/http" + "strings" + "regexp" + "github.com/dlclark/regexp2" +) +var rusername *regexp.Regexp +var remail *regexp2.Regexp +var rpassword *regexp2.Regexp +func register(w http.ResponseWriter, r *http.Request) { + var err error + registerstruct := registertmpl{} + if r.Method == http.MethodPost { + var newAccount account + var newRbuMember *discordgo.Member + var split = strings.Split(r.FormValue("discordUser"), "#") + newAccount = account{ + email: r.FormValue("email"), + username: r.FormValue("username"), + password: r.FormValue("password"), + } + if len(split) == 2 { + 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 { + 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.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) + log(err) + var dmChannel *discordgo.Channel + dmChannel, err = discord.UserChannelCreate(newRbuMember.User.ID) + log(err) + discord.ChannelMessageSend(dmChannel.ID, "Bitte klicke auf den Link, um die Erstellung des Accounts abzuschließen.\nhttp://localhost:8080/submit?token=" + token) + cacheAccounts.Set(token, newAccount) + } + registerReturn: err = registerTmpl.Execute(w, registerstruct) + log(err) +} diff --git a/tmpl/register.html b/tmpl/register.html index e9c93d2..37190ab 100644 --- a/tmpl/register.html +++ b/tmpl/register.html @@ -1,34 +1,105 @@ -{{if .Success}} -
Bitte klicke in discord auf den Bestätigungslink.
-{{else}} -Ungültiger Benutzername. Benutzer müssen klein geschrieben werden, dürfen höchstens aus 40 Zeichen bestehen. Alle Zeichen müssen zudem alphanumerisch sein. "-", "_" und "." sind auch erlaubt.
-{{end}} -{{if .WrongAccount.Email}} -Ungültige E-Mail-Adresse.
-{{end}} -{{if .WrongAccount.Pass}} -Ungültiges Passwort. Passwörter müssen 8 bis 255 Zeichen lang sein. Außerdem muss ein Groß- und Kleichbuchstabe, eine Ziffer und ein Sonderzeichen enthalten sein
-{{end}} -{{if .WrongAccount.DiscordUser}} -Discordbenutzer ist nicht auf den RBU server. Beachte den tag wegzulassen.
-{{end}} -{{if .AlreadyEsitsInDatabase.Username}} -Diesen Benutzername ist leider schon vergeben.
-{{end}} -{{if .AlreadyEsitsInDatabase.DiscordUsername}} -Dieses RBU Mitglied hat bereits einen Account.
-{{end}} \ No newline at end of file + + + +
+ 
Bitte klicke in discord auf den Bestätigungslink.
+ {{else}} +Ungültiger Benutzername. Benutzer müssen klein geschrieben werden, dürfen höchstens aus 40 Zeichen bestehen. Alle Zeichen müssen zudem alphanumerisch sein. "-", "_" und "." sind auch erlaubt.
+ {{end}} + {{if .WrongAccount.Email}} +Ungültige E-Mail-Adresse.
+ {{end}} + {{if .WrongAccount.Pass}} +Ungültiges Passwort. Passwörter müssen 8 bis 255 Zeichen lang sein. Außerdem muss ein Groß- und Kleichbuchstabe, eine Ziffer und ein Sonderzeichen enthalten sein
+ {{end}} + {{if .WrongAccount.DiscordUser}} +Discordbenutzer ist nicht auf den RBU server. Beachte den tag anzugeben.
+ {{end}} + {{if .AlreadyEsitsInDatabase.Username}} +Diesen Benutzername ist leider schon vergeben.
+ {{end}} + {{if .AlreadyEsitsInDatabase.DiscordUsername}} +Dieses RBU Mitglied hat bereits einen Account.
+ {{end}} +