add error handling for reading configuration #1
@ -14,40 +14,54 @@ import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// SignupPage is the signup page handler
|
||||
type formValues struct {
|
||||
Username string
|
||||
Email string
|
||||
SshPublicKey string
|
||||
IPAddress string
|
||||
CaptchaResponse string
|
||||
}
|
||||
|
||||
type CaptchaResponse struct {
|
||||
Success bool `json:"success"`
|
||||
}
|
||||
|
||||
// SignupPage is the signup page handler
|
||||
func SignupPage(c *fiber.Ctx) error {
|
||||
SignupIP, SignupIPExists := os.LookupEnv("PUBLAPI_SIGNUP_IP")
|
||||
if SignupIPExists == true {
|
||||
if SignupIPExists {
|
||||
if c.IP() != SignupIP {
|
||||
log.Info("Request made from invalid IP: ", c.IP())
|
||||
return c.SendStatus(fiber.StatusForbidden)
|
||||
}
|
||||
}
|
||||
username := c.FormValue("username")
|
||||
email := c.FormValue("email")
|
||||
ssh := c.FormValue("ssh")
|
||||
ip := c.FormValue("ip")
|
||||
captchaResp := c.FormValue("h-captcha-response")
|
||||
|
||||
if captchaResp == "" {
|
||||
formValues := formValues{
|
||||
Username: c.FormValue("username"),
|
||||
Email: c.FormValue("email"),
|
||||
SshPublicKey: c.FormValue("ssh"),
|
||||
IPAddress: c.FormValue("ip"),
|
||||
CaptchaResponse: c.FormValue("h-captcha-response"),
|
||||
}
|
||||
|
||||
if formValues.CaptchaResponse == "" {
|
||||
log.Error("Nice try, but the registration won't work unless you answer the captcha.")
|
||||
return c.SendStatus(fiber.StatusBadRequest)
|
||||
}
|
||||
|
||||
if username == "" || email == "" || ssh == "" || ip == "" {
|
||||
log.Error("username, email, ssh and ip must be filled", username, email, ssh, ip)
|
||||
if formValues.Username == "" || formValues.Email == "" || formValues.SshPublicKey == "" || formValues.IPAddress == "" {
|
||||
log.Error("username, email, ssh and ip must be filled", formValues.Username, formValues.Email, formValues.SshPublicKey, formValues.IPAddress)
|
||||
return c.SendStatus(fiber.StatusBadRequest)
|
||||
}
|
||||
raid, ok := os.LookupEnv("PUBLAPI_RAID_MODE")
|
||||
if !ok || raid == "1" {
|
||||
log.Warn(
|
||||
"PUBLAPI_RAID_MODE is on, accepting every request as OK and not doing anything...\n User info: ",
|
||||
username,
|
||||
formValues.Username,
|
||||
" ",
|
||||
email,
|
||||
formValues.Email,
|
||||
" ",
|
||||
ip,
|
||||
formValues.IPAddress,
|
||||
" ",
|
||||
)
|
||||
return c.SendStatus(fiber.StatusOK)
|
||||
@ -55,10 +69,10 @@ func SignupPage(c *fiber.Ctx) error {
|
||||
|
||||
// Check the captcha validation.
|
||||
|
||||
captchaSecret, ok := os.LookupEnv("PUBLAPI_CAPTCHA_SECRET")
|
||||
captchaSecret, _ := os.LookupEnv("PUBLAPI_CAPTCHA_SECRET")
|
||||
|
||||
params := url.Values{}
|
||||
params.Add("response", captchaResp)
|
||||
params.Add("response", formValues.CaptchaResponse)
|
||||
params.Add("secret", captchaSecret)
|
||||
body := strings.NewReader(params.Encode())
|
||||
|
||||
@ -82,30 +96,27 @@ func SignupPage(c *fiber.Ctx) error {
|
||||
sb := string(bod)
|
||||
log.Info("Captcha response: ", sb)
|
||||
|
||||
type CaptchaResponse struct {
|
||||
Success bool `json:"success"`
|
||||
}
|
||||
var captchaResponse CaptchaResponse
|
||||
captchaResponse := CaptchaResponse{}
|
||||
err = json.Unmarshal([]byte(sb), &captchaResponse)
|
||||
if err != nil {
|
||||
log.Error("Error unmarshalling captcha response", err)
|
||||
}
|
||||
|
||||
if captchaResponse.Success == false {
|
||||
if !captchaResponse.Success {
|
||||
log.Error("Captcha validation failed")
|
||||
return c.JSON(fiber.Map{
|
||||
"username": username,
|
||||
"message": "Sorry! But the captcha validation failed. Please try again.",
|
||||
"username": formValues.CaptchaResponse,
|
||||
"message": "Sorry, but the captcha validation failed. Please try again.",
|
||||
"status": c.Response().StatusCode(),
|
||||
})
|
||||
} else {
|
||||
// Check if user already exists
|
||||
// We'll check the home folder and see if the username folder exists.
|
||||
_, err := os.Stat("/home/" + username)
|
||||
_, err := os.Stat("/home/" + formValues.Username)
|
||||
if err == nil {
|
||||
log.Error("User already exists : ", username)
|
||||
log.Error("User already exists : ", formValues.Username)
|
||||
return c.JSON(fiber.Map{
|
||||
"username": username,
|
||||
"username": formValues.Username,
|
||||
"message": "User already exists. Please choose a different username.",
|
||||
"status": c.Response().StatusCode(),
|
||||
})
|
||||
@ -113,28 +124,28 @@ func SignupPage(c *fiber.Ctx) error {
|
||||
|
||||
// create user file
|
||||
|
||||
f, err := os.Create("/var/publapi/users/" + username + ".sh")
|
||||
f, err := os.Create("/var/publapi/users/" + formValues.Username + ".sh")
|
||||
if err != nil {
|
||||
log.Error("Error creating user file", err)
|
||||
return c.SendStatus(fiber.StatusInternalServerError)
|
||||
}
|
||||
defer f.Close()
|
||||
chmoderr := os.Chmod("/var/publapi/users/"+username+".sh", 0700)
|
||||
chmoderr := os.Chmod("/var/publapi/users/"+formValues.Username+".sh", 0700)
|
||||
if chmoderr != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
Bashscript := strings.ReplaceAll(utils.Bashscript, "{{sshkey}}", ssh)
|
||||
Bashscript = strings.ReplaceAll(Bashscript, "{{email}}", email)
|
||||
Bashscript = strings.ReplaceAll(Bashscript, "{{username}}", username)
|
||||
bashScript := strings.ReplaceAll(utils.BashScript, "{{sshkey}}", formValues.SshPublicKey)
|
||||
bashScript = strings.ReplaceAll(bashScript, "{{email}}", formValues.Email)
|
||||
bashScript = strings.ReplaceAll(bashScript, "{{username}}", formValues.Username)
|
||||
// write to file
|
||||
_, err = f.WriteString(Bashscript)
|
||||
_, err = f.WriteString(bashScript)
|
||||
if err != nil {
|
||||
log.Error("Error writing to user file", err)
|
||||
return c.SendStatus(fiber.StatusInternalServerError)
|
||||
}
|
||||
|
||||
log.Info(
|
||||
"Registration request for " + username + " has been submitted by the frontend and has been written to /var/publapi/users/" + username + ".sh",
|
||||
"Registration request for " + formValues.Username + " has been submitted by the frontend and has been written to /var/publapi/users/" + formValues.Username + ".sh",
|
||||
)
|
||||
|
||||
// send notification to user that their reg request was sent
|
||||
@ -150,14 +161,14 @@ func SignupPage(c *fiber.Ctx) error {
|
||||
shoutrrrUrl := os.Getenv("PUBLAPI_NOTIFY_SHOUTRRRURL") + os.Getenv("PUBLAPI_NOTIFY_ROOMS")
|
||||
err = shoutrrr.Send(
|
||||
shoutrrrUrl,
|
||||
"New user signup! Please review /var/publapi/users/"+username+".sh to approve or deny the user. IP: "+ip+" Email: "+email,
|
||||
"New user signup! Please review /var/publapi/users/"+formValues.Username+".sh to approve or deny the user. IP: "+formValues.IPAddress+" Email: "+formValues.Email,
|
||||
)
|
||||
if err != nil {
|
||||
log.Error("Error sending notification to admins", err)
|
||||
//return c.SendStatus(fiber.StatusInternalServerError)
|
||||
}
|
||||
return c.JSON(fiber.Map{
|
||||
"username": username,
|
||||
"username": formValues.Username,
|
||||
"message": "User created! Please allow us 24 hours or more to review your account.",
|
||||
"status": c.Response().StatusCode(),
|
||||
})
|
||||
|
@ -16,14 +16,14 @@ import (
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
type Userstruct struct {
|
||||
type UserStruct struct {
|
||||
Status int `json:"status"`
|
||||
Online int `json:"online"`
|
||||
Total int `json:"total"`
|
||||
Users []Userinfo `json:"users"`
|
||||
Users []UserInfo `json:"users"`
|
||||
}
|
||||
|
||||
type Userinfo struct {
|
||||
type UserInfo struct {
|
||||
Name string `json:"name"`
|
||||
FullName string `json:"fullName"`
|
||||
Desc string `json:"desc"`
|
||||
@ -38,7 +38,7 @@ type Userinfo struct {
|
||||
Loc string `json:"loc"`
|
||||
}
|
||||
|
||||
type ByAdminAndName []Userinfo
|
||||
type ByAdminAndName []UserInfo
|
||||
|
||||
func (a ByAdminAndName) Len() int { return len(a) }
|
||||
func (a ByAdminAndName) Less(i, j int) bool {
|
||||
@ -58,7 +58,7 @@ func UserError(message string, username string, err error) {
|
||||
log.Error("error", message, log.Any("err", err), "username", username)
|
||||
}
|
||||
|
||||
func userdata(username, usersonline, ops string) Userinfo {
|
||||
func userData(username, usersonline, ops string) UserInfo {
|
||||
regex := "(^| )" + username + "($| )"
|
||||
isonline, err := regexp.MatchString(string(regex), string(usersonline))
|
||||
if err != nil {
|
||||
@ -80,7 +80,7 @@ func userdata(username, usersonline, ops string) Userinfo {
|
||||
if error != nil {
|
||||
if os.IsNotExist(error) {
|
||||
log.Error(username + " does not have a meta-info.toml")
|
||||
var user Userinfo
|
||||
var user UserInfo
|
||||
user.Name = username
|
||||
user.Created, _ = strconv.Atoi(crdstr)
|
||||
if isonline {
|
||||
@ -99,7 +99,7 @@ func userdata(username, usersonline, ops string) Userinfo {
|
||||
viper.SetConfigFile(filename)
|
||||
if err := viper.ReadInConfig(); err != nil {
|
||||
log.Error("message", "Couldn't read a users meta-info.toml file.", "error", log.Any("err", err), "user", username)
|
||||
user := Userinfo{
|
||||
user := UserInfo{
|
||||
Name: username,
|
||||
}
|
||||
user.Created, _ = strconv.Atoi(crdstr)
|
||||
@ -115,27 +115,25 @@ func userdata(username, usersonline, ops string) Userinfo {
|
||||
}
|
||||
return user
|
||||
}
|
||||
var user Userinfo
|
||||
user = Userinfo{}
|
||||
user.Name = username
|
||||
user := UserInfo{
|
||||
Name: username,
|
||||
FullName: viper.GetString("fullname"),
|
||||
Capsule: viper.GetString("gemini"),
|
||||
Website: viper.GetString("website"),
|
||||
Desc: viper.GetString("description"),
|
||||
Email: viper.GetString("email"),
|
||||
Matrix: viper.GetString("matrix"),
|
||||
Fediverse: viper.GetString("fediverse"),
|
||||
Loc: viper.GetString("location"),
|
||||
Op: false,
|
||||
Online: false,
|
||||
}
|
||||
user.Created, _ = strconv.Atoi(crdstr)
|
||||
user.FullName = viper.GetString("fullname")
|
||||
user.Capsule = viper.GetString("gemini")
|
||||
user.Website = viper.GetString("website")
|
||||
user.Desc = viper.GetString("description")
|
||||
user.Email = viper.GetString("email")
|
||||
user.Matrix = viper.GetString("matrix")
|
||||
user.Fediverse = viper.GetString("fediverse")
|
||||
user.Loc = viper.GetString("location")
|
||||
if isop {
|
||||
user.Op = true
|
||||
} else {
|
||||
user.Op = false
|
||||
}
|
||||
if isonline {
|
||||
user.Online = true
|
||||
} else {
|
||||
user.Online = false
|
||||
}
|
||||
return user
|
||||
}
|
||||
@ -148,18 +146,18 @@ func UsersPage(c *fiber.Ctx) error {
|
||||
})
|
||||
}
|
||||
// Get the number of users online
|
||||
usersonline, err := exec.Command("bash", "-c", "/usr/bin/users").Output()
|
||||
usersOnline, err := exec.Command("bash", "-c", "/usr/bin/users").Output()
|
||||
if err != nil {
|
||||
log.Error("error", log.Any("error", err))
|
||||
return c.SendStatus(fiber.StatusInternalServerError)
|
||||
}
|
||||
usersonlinestr := string(usersonline)
|
||||
usersonlinededup := utils.Dedup(usersonlinestr)
|
||||
usersOnlineStr := string(usersOnline)
|
||||
usersOnlineDedup := utils.Dedup(usersOnlineStr)
|
||||
var output int
|
||||
if strings.Contains(usersonlinededup, " ") {
|
||||
outputa := int(strings.Count(usersonlinededup, " "))
|
||||
if strings.Contains(usersOnlineDedup, " ") {
|
||||
outputa := int(strings.Count(usersOnlineDedup, " "))
|
||||
output = outputa + 1
|
||||
} else if usersonlinededup == "" {
|
||||
} else if usersOnlineDedup == "" {
|
||||
output = 0
|
||||
} else {
|
||||
output = 1
|
||||
@ -181,23 +179,23 @@ func UsersPage(c *fiber.Ctx) error {
|
||||
userstr2 := strings.TrimSuffix(userstr, "\n")
|
||||
usersarr := strings.Split(userstr2, "\n")
|
||||
// Fill user info
|
||||
var userinfostruct []Userinfo
|
||||
var userInfoStruct []UserInfo
|
||||
for i := 0; i < len(usersarr); i++ {
|
||||
uname := string(usersarr[i])
|
||||
userinfostruct = append(
|
||||
userinfostruct,
|
||||
userdata(
|
||||
userInfoStruct = append(
|
||||
userInfoStruct,
|
||||
userData(
|
||||
uname,
|
||||
strings.TrimSuffix(usersonlinededup, "\n"),
|
||||
strings.TrimSuffix(usersOnlineDedup, "\n"),
|
||||
strings.TrimSuffix(opstr, "\n"),
|
||||
),
|
||||
)
|
||||
}
|
||||
sort.Sort(ByAdminAndName(userinfostruct))
|
||||
data := Userstruct{
|
||||
sort.Sort(ByAdminAndName(userInfoStruct))
|
||||
data := UserStruct{
|
||||
Status: c.Response().StatusCode(),
|
||||
Online: output,
|
||||
Users: userinfostruct,
|
||||
Users: userInfoStruct,
|
||||
Total: int(strings.Count(userstr, "\n")),
|
||||
}
|
||||
return c.JSON(data)
|
||||
|
@ -6,7 +6,7 @@ import (
|
||||
)
|
||||
|
||||
//go:embed signup-script-template
|
||||
var Bashscript string
|
||||
var BashScript string
|
||||
|
||||
func Dedup(input string) string {
|
||||
unique := []string{}
|
||||
|
Loading…
Reference in New Issue
Block a user