add minceraft linkage

This commit is contained in:
stryan 2020-11-10 17:58:24 -05:00
parent fe54be6217
commit 98e1d7e774
9 changed files with 201 additions and 7 deletions

View File

@ -8,12 +8,13 @@ import (
) )
type LdapConfig struct { type LdapConfig struct {
Url string Url string
AdminUser string AdminUser string
UserAttr string UserAttr string
UserOu string UserOu string
LdapDc string MineUserOu string
LdapPass string LdapDc string
LdapPass string
} }
type MailConfig struct { type MailConfig struct {
@ -64,6 +65,7 @@ func LoadConfig() (*Config, error) {
l.AdminUser = viper.GetString("adminUser") l.AdminUser = viper.GetString("adminUser")
l.UserAttr = viper.GetString("userAttr") l.UserAttr = viper.GetString("userAttr")
l.UserOu = viper.GetString("userOu") l.UserOu = viper.GetString("userOu")
l.MineUserOu = viper.GetString("mineUserOu")
l.LdapDc = viper.GetString("ldapDc") l.LdapDc = viper.GetString("ldapDc")
l.LdapPass = viper.GetString("ldapPass") l.LdapPass = viper.GetString("ldapPass")
c.Secret = viper.GetString("secret") c.Secret = viper.GetString("secret")

64
ldap.go
View File

@ -9,6 +9,34 @@ import (
"github.com/go-ldap/ldap" "github.com/go-ldap/ldap"
) )
func createLDAPMCAccount(uname, mcuname string) error {
if uname == "" || mcuname == "" {
log.Printf("error: missing field\n")
return errors.New("Missing field")
}
url := Conf.Ldap.Url
newdn := fmt.Sprintf("%v=%v,%v,%v", Conf.Ldap.UserAttr, mcuname, Conf.Ldap.MineUserOu, Conf.Ldap.LdapDc)
binddn := fmt.Sprintf("%v,%v", Conf.Ldap.AdminUser, Conf.Ldap.LdapDc)
maindn := fmt.Sprintf("%v=%v,%v,%v", Conf.Ldap.UserAttr, uname, Conf.Ldap.UserOu, Conf.Ldap.LdapDc)
l, err := ldap.DialURL(url)
if err != nil {
return err
}
defer l.Close()
err = l.Bind(binddn, Conf.Ldap.LdapPass)
if err != nil {
return err
}
addReq := ldap.NewAddRequest(newdn, []ldap.Control{})
addReq.Attribute("objectClass", []string{"top", "account"})
addReq.Attribute("seeAlso", []string{maindn})
if err := l.Add(addReq); err != nil {
log.Printf("error adding service:", addReq, err)
return errors.New("Error creating LDAP account")
}
return nil
}
func createLDAPAccount(uname string, pwd string, email string) error { func createLDAPAccount(uname string, pwd string, email string) error {
if uname == "" || pwd == "" || email == "" { if uname == "" || pwd == "" || email == "" {
log.Printf("error: missing field\n") log.Printf("error: missing field\n")
@ -167,7 +195,41 @@ func findLDAPAccountByEmail(email string) (string, error) {
return entry.GetAttributeValue(Conf.Ldap.UserAttr), nil return entry.GetAttributeValue(Conf.Ldap.UserAttr), nil
} }
func findLDAPMCAccount(uname string) (string, error) {
url := Conf.Ldap.Url
binddn := fmt.Sprintf("%v,%v", Conf.Ldap.AdminUser, Conf.Ldap.LdapDc)
basedn := fmt.Sprintf("%v,%v", Conf.Ldap.MineUserOu, Conf.Ldap.LdapDc)
userdn := fmt.Sprintf("%v=%v,%v,%v", Conf.Ldap.UserAttr, uname, Conf.Ldap.UserOu, Conf.Ldap.LdapDc)
l, err := ldap.DialURL(url)
if err != nil {
return "", err
}
defer l.Close()
err = l.Bind(binddn, Conf.Ldap.LdapPass)
if err != nil {
return "", err
}
result, err := l.Search(ldap.NewSearchRequest(
basedn,
ldap.ScopeWholeSubtree,
ldap.NeverDerefAliases,
0,
0,
false,
fmt.Sprintf("(&(objectClass=account)(seeAlso=%s))", userdn),
[]string{"uid"},
nil,
))
if err != nil {
return "", err
}
if len(result.Entries) != 1 {
err_text := fmt.Sprintf("Error finding user: Wanted 1 result, got %v\n", len(result.Entries))
return "", errors.New(err_text)
}
entry := result.Entries[0]
return entry.GetAttributeValue("uid"), nil
}
func findLDAPAccountForDisplay(uname string) (User, error) { func findLDAPAccountForDisplay(uname string) (User, error) {
url := Conf.Ldap.Url url := Conf.Ldap.Url
binddn := fmt.Sprintf("%v,%v", Conf.Ldap.AdminUser, Conf.Ldap.LdapDc) binddn := fmt.Sprintf("%v,%v", Conf.Ldap.AdminUser, Conf.Ldap.LdapDc)

View File

@ -29,6 +29,10 @@ func main() {
router.HandleFunc("/profile/view", profilePage).Methods("GET") router.HandleFunc("/profile/view", profilePage).Methods("GET")
router.HandleFunc("/profile/edit", profileEditPage).Methods("GET") router.HandleFunc("/profile/edit", profileEditPage).Methods("GET")
router.HandleFunc("/profile/edit", profileEdit).Methods("POST") router.HandleFunc("/profile/edit", profileEdit).Methods("POST")
router.HandleFunc("/minecraft", minecraftPage).Methods("GET")
router.HandleFunc("/minecraft/link", minecraftLink).Methods("POST")
router.HandleFunc("/minecraft/link/success", minecraftLinkSuccessPage).Methods("GET")
router.HandleFunc("/minecraft/link/error", minecraftLinkErrorPage).Methods("GET")
router.HandleFunc("/passwordreset", resetPageFront).Methods("GET") router.HandleFunc("/passwordreset", resetPageFront).Methods("GET")
router.HandleFunc("/passwordreset", resetLookup).Methods("POST") router.HandleFunc("/passwordreset", resetLookup).Methods("POST")
router.HandleFunc("/passwordresetform", resetPageBack).Methods("GET") router.HandleFunc("/passwordresetform", resetPageBack).Methods("GET")

28
minecraft.go Normal file
View File

@ -0,0 +1,28 @@
package main
import (
"log"
"net/http"
)
func minecraftLink(res http.ResponseWriter, req *http.Request) {
uname := getUserName(req)
if uname == "" {
http.Redirect(res, req, "/", 302)
}
mcname := req.FormValue("mcusername")
if mcname != "" {
log.Printf("linked MC %v to LDAP %v\n", mcname, uname)
err := createLDAPMCAccount(uname, mcname)
if err != nil {
log.Printf("Error linking MC account: %v\n", err)
http.Redirect(res, req, "/minecraft/link/error", 302)
} else {
http.Redirect(res, req, "/minecraft/link/success", 302)
}
} else {
log.Println("couldn't get MC username")
http.Redirect(res, req, "/minecraft/link/error", 302)
}
return
}

View File

@ -3,6 +3,7 @@
{{if .LoggedIn }} {{if .LoggedIn }}
<p><a href="/token">Get Token</a></p> <p><a href="/token">Get Token</a></p>
<p><a href="/profile/view">Profile</a></p> <p><a href="/profile/view">Profile</a></p>
<p><a href="/minecraft">Minecraft Account Status</a></p>
{{else}} {{else}}
<p><a href="/register">Register</a></p> <p><a href="/register">Register</a></p>
<p><a href="/passwordreset">Reset Password</a></p> <p><a href="/passwordreset">Reset Password</a></p>

24
templates/minecraft.html Normal file
View File

@ -0,0 +1,24 @@
{{ define "minecraft" }}
{{ template "header" .}}
<body>
<div>
{{if .Linked }}
<p>Your Minecraft Account {{ .MinecraftAccount }} is linked with {{ .Username }}.</p>
{{ else }}
<form method="POST" action="/minecraft/link">
<p>Enter your Minecraft Username and click the button to link it to your Saintnet account.</p>
<p>This will add you to any connected servers whitelist</p>
<table>
<tr>
<td>Minecraft Username:</td>
<td><input type="string" placeholder='Minecraft username' name="mcusername" value="Minecraft username"></td>
</tr>
<tr>
<td><input type="submit" value="Link"</td>
</tr>
</table>
</form>
{{end}}
</div>
{{template "footer" .}}
{{end}}

View File

@ -0,0 +1,8 @@
{{ define "minecraft_error" }}
{{ template "header" .}}
<p>Unable to link your Minecraft account due to the following error:</p>
<p>{{.Error}}</p>
<p>Please try again or let the admin know.</p>
<p><a href="/">Return to homepage</a></p>
{{template "footer" .}}
{{ end }}

View File

@ -0,0 +1,6 @@
{{ define "minecraft_success" }}
{{ template "header" .}}
<p>Your Minecraft account has been linked</p>
<p><a href="/">Return to homepage</a></p>
{{template "footer" .}}
{{ end }}

59
web.go
View File

@ -55,6 +55,65 @@ func profileEditPage(res http.ResponseWriter, req *http.Request) {
} }
tpl.ExecuteTemplate(res, "profile_edit", data) tpl.ExecuteTemplate(res, "profile_edit", data)
} }
func minecraftPage(res http.ResponseWriter, req *http.Request) {
log.Println("GET /minecraft")
u := getUserName(req)
if u == "" {
http.Redirect(res, req, "/", 302)
} else {
mcuser, err := findLDAPMCAccount(u)
mclink := true
if err != nil {
mclink = false
mcuser = "N/A"
}
data := struct {
Title string
Username string
LoggedIn bool
Linked bool
MinecraftAccount string
}{
"Link Minecraft Account",
u,
true,
mclink,
mcuser,
}
tpl.ExecuteTemplate(res, "minecraft", data)
}
}
func minecraftLinkSuccessPage(res http.ResponseWriter, req *http.Request) {
log.Println("GET /minecraft/link/success")
data := struct {
Title string
Username string
LoggedIn bool
}{
"Minecraft Link Success",
"",
true,
}
tpl.ExecuteTemplate(res, "minecraft_success", data)
return
}
func minecraftLinkErrorPage(res http.ResponseWriter, req *http.Request) {
log.Println("GET /minecraft/link/error")
data := struct {
Title string
Username string
LoggedIn bool
Error string
}{
"Minecraft Link Failure",
"",
true,
"Undefined",
}
tpl.ExecuteTemplate(res, "minecraft_error", data)
return
}
func resetPageFront(res http.ResponseWriter, req *http.Request) { func resetPageFront(res http.ResponseWriter, req *http.Request) {
log.Println("GET /passwordreset") log.Println("GET /passwordreset")
u := getUserName(req) u := getUserName(req)