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