Compare commits

...

2 Commits

Author SHA1 Message Date
e557cfa257 refactoring 2020-12-22 12:44:16 +01:00
4fc51f86e4 login page 2020-12-21 18:53:42 +01:00
4 changed files with 115 additions and 37 deletions

62
src/login.go Normal file
View File

@ -0,0 +1,62 @@
package main
import (
"time"
"net/http"
"bytes"
"github.com/cornelk/hashmap"
)
type loginStruct struct {
FalsePassword bool
}
var sessions hashmap.HashMap
const sessionName string = "session"
const sessionTimeout time.Duration = 10 * 24 * time.Hour
func login(w http.ResponseWriter, r *http.Request) {
loginStruct := loginStruct{}
var login bool = false
if loggedIn(r) {
http.Redirect(w, r, "dash", http.StatusSeeOther)
return
}
if r.Method == http.MethodPost {
var username string = r.FormValue("username")
var password string = r.FormValue("password")
var hash []byte
var salt []byte
db.QueryRow("SELECT hash,salt FROM account WHERE username = ?", username).Scan(&hash, &salt)
login = bytes.Equal(hashFunc([]byte(password), salt), hash)
loginStruct.FalsePassword = !login
if login {
key, err := GenerateRandomString(64)
log(err)
cookie := http.Cookie{
Name: sessionName,
Value: key,
Expires: time.Now().Add(sessionTimeout),
HttpOnly: true,
Secure: true,
}
http.SetCookie(w, &cookie)
sessions.Set(key, username)
go deleteSession(key)
http.Redirect(w, r, "dash", http.StatusSeeOther)
}
}
if r.Method == http.MethodGet || !login {
runTemplate(w, loginTmpl, loginStruct)
}
}
func loggedIn(r *http.Request) bool {
key, err := r.Cookie(sessionName)
if err != nil {
return false
}
_, valid := sessions.GetStringKey(key.Value)
return valid
}
func deleteSession(key string) {
time.Sleep(sessionTimeout)
sessions.Del(key)
}

View File

@ -12,7 +12,6 @@ import (
"net/http"
"os"
"regexp"
"github.com/cornelk/hashmap"
"code.gitea.io/sdk/gitea"
"fmt"
"golang.org/x/crypto/argon2"
@ -20,36 +19,11 @@ import (
var discord *discordgo.Session
var secret secrets_json
var config config_json
var cacheAccounts hashmap.HashMap
var db *sql.DB
var giteaClient *gitea.Client
var registerTmpl *template.Template
var submitTmpl *template.Template
type account struct {
email string
username string
password string
discordUsername string
discordTag string
discordId string
}
type WrongAccount struct {
User bool
Pass bool
Email bool
DiscordUser bool
}
type registertmpl struct {
Success bool
WrongAccount WrongAccount
AlreadyEsitsInDatabase struct{
Username bool
DiscordUsername bool
}
}
type SubmitStruct struct {
Success bool
}
var loginTmpl *template.Template
type secrets_json struct {
DiscordToken string `json:"discordToken"`
MysqlIndentify string `json:"mysqlIndentify"`
@ -100,10 +74,13 @@ func main() {
_ = moodle
registerTmpl = template.Must(template.ParseFiles("tmpl/register.html"))
submitTmpl = template.Must(template.ParseFiles("tmpl/submit.html"))
loginTmpl = template.Must(template.ParseFiles("tmpl/login.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", register)
http.HandleFunc("/submit", submit)
http.HandleFunc("/login", login)
http.ListenAndServe(":" + fmt.Sprint(config.Port), nil)
}
@ -113,6 +90,11 @@ func log(err error) {
}
}
func hash(password []byte, salt []byte) []byte {
func hashFunc(password []byte, salt []byte) []byte {
return argon2.IDKey(password, salt, 1, 64*1024, 4, 32)
}
func runTemplate(w http.ResponseWriter, template *template.Template, templateData interface{}) {
w.Header().Set("Content-Type", "text/html")
var err error = template.Execute(w, templateData)
log(err)
}

View File

@ -10,12 +10,38 @@ import (
"time"
"code.gitea.io/sdk/gitea"
"crypto/rand"
"github.com/cornelk/hashmap"
)
type account struct {
email string
username string
password string
discordUsername string
discordTag string
discordId string
}
type WrongAccount struct {
User bool
Pass bool
Email bool
DiscordUser bool
}
type registertmpl struct {
Success bool
WrongAccount WrongAccount
AlreadyEsitsInDatabase struct{
Username bool
DiscordUsername bool
}
}
type SubmitStruct struct {
Success bool
}
var cacheAccounts hashmap.HashMap
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
@ -43,8 +69,8 @@ func register(w http.ResponseWriter, r *http.Request) {
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 {
@ -58,8 +84,7 @@ func register(w http.ResponseWriter, r *http.Request) {
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)
registerReturn: runTemplate(w, registerTmpl, registerstruct)
}
func submit(w http.ResponseWriter, r *http.Request) {
var err error
@ -74,9 +99,9 @@ func register(w http.ResponseWriter, r *http.Request) {
var account account = accInter.(account)
cacheAccounts.Del(token)
salt := make([]byte, 32)
_, err := rand.Read(salt)
_, err = rand.Read(salt)
log(err)
hash := hash([]byte(account.password), salt)
hash := hashFunc([]byte(account.password), salt)
// add user to the database
query := "INSERT INTO account(username, email, hash, salt, discordUserId) VALUES (?, ?, ?, ?, ?)"
ctx, cancelfunc := context.WithTimeout(context.Background(), 5*time.Second)
@ -101,8 +126,7 @@ func register(w http.ResponseWriter, r *http.Request) {
}
}
submitReturn: err = submitTmpl.Execute(w, submitStruct)
log(err)
submitReturn: runTemplate(w, submitTmpl, submitStruct)
}
func getRbuMember(user string, tag string) (*discordgo.Member, bool) {
allUsers, err := discord.GuildMembers(secret.DiscordServerID, "0", 1000)

10
tmpl/login.html Normal file
View File

@ -0,0 +1,10 @@
{{if .FalsePassword}}
<p>falches Passwort</p>
{{end}}
<form method="POST" class="responsive">
<label class="responsive">Benutzername:</label><br/>
<input class="responsive" type="text" name="username"><br/>
<label class="responsive">Passwort:</label><br/>
<input class="responsive" type="password" name="password"><br/>
<input type="submit" name="login" value="login"class="btn active responsive">
</form>