2023-01-07 21:03:51 +05:30
package pages
import (
2023-07-11 02:53:29 +05:30
"encoding/json"
2024-02-27 19:35:13 +05:30
"io"
2023-07-11 02:53:29 +05:30
"net/http"
"net/url"
"os"
"strings"
2023-01-21 22:19:17 +05:30
"github.com/ProjectSegfault/publapi/utils"
2023-01-07 21:03:51 +05:30
"github.com/containrrr/shoutrrr"
2023-02-05 19:00:47 +05:30
"github.com/gofiber/fiber/v2"
2023-01-07 22:24:04 +05:30
log "github.com/sirupsen/logrus"
2023-01-07 21:03:51 +05:30
)
// SignupPage is the signup page handler
2023-07-11 02:53:29 +05:30
2023-01-07 21:03:51 +05:30
func SignupPage ( c * fiber . Ctx ) error {
2023-02-18 15:20:24 +05:30
SignupIP , SignupIPExists := os . LookupEnv ( "PUBLAPI_SIGNUP_IP" )
if SignupIPExists == true {
if c . IP ( ) != SignupIP {
log . Info ( "Request made from invalid IP: " , c . IP ( ) )
return c . SendStatus ( fiber . StatusForbidden )
}
}
2023-01-07 21:03:51 +05:30
username := c . FormValue ( "username" )
email := c . FormValue ( "email" )
2023-01-17 20:36:47 +05:30
ssh := c . FormValue ( "ssh" )
2023-01-21 21:54:33 +05:30
ip := c . FormValue ( "ip" )
2023-07-11 02:53:29 +05:30
captchaResp := c . FormValue ( "h-captcha-response" )
if captchaResp == "" {
log . Error ( "Nice try, but the registration won't work unless you answer the captcha." )
return c . SendStatus ( fiber . StatusBadRequest )
}
2023-01-21 21:54:33 +05:30
if username == "" || email == "" || ssh == "" || ip == "" {
log . Error ( "username, email, ssh and ip must be filled" , username , email , ssh , ip )
2023-01-17 20:36:47 +05:30
return c . SendStatus ( fiber . StatusBadRequest )
}
2023-05-27 15:54:23 +05:30
raid , ok := os . LookupEnv ( "PUBLAPI_RAID_MODE" )
if ! ok || raid == "1" {
2023-07-11 02:53:29 +05:30
log . Warn (
"PUBLAPI_RAID_MODE is on, accepting every request as OK and not doing anything...\n User info: " ,
username ,
" " ,
email ,
" " ,
ip ,
" " ,
)
2023-05-27 15:54:23 +05:30
return c . SendStatus ( fiber . StatusOK )
}
2023-01-07 21:03:51 +05:30
2023-07-11 02:53:29 +05:30
// Check the captcha validation.
captchaSecret , ok := os . LookupEnv ( "PUBLAPI_CAPTCHA_SECRET" )
params := url . Values { }
params . Add ( "response" , captchaResp )
params . Add ( "secret" , captchaSecret )
body := strings . NewReader ( params . Encode ( ) )
req , err := http . NewRequest ( "POST" , "https://hcaptcha.com/siteverify" , body )
2023-01-07 21:03:51 +05:30
if err != nil {
2023-07-11 02:53:29 +05:30
// handle err
2023-01-21 14:26:07 +05:30
}
2023-07-11 02:53:29 +05:30
req . Header . Set ( "Content-Type" , "application/x-www-form-urlencoded" )
resp , err := http . DefaultClient . Do ( req )
2023-01-07 21:03:51 +05:30
if err != nil {
2023-07-11 02:53:29 +05:30
log . Error ( "Something went wrong fetching the HCatpcha API: " , err )
2023-01-07 21:03:51 +05:30
}
2023-07-11 02:53:29 +05:30
defer resp . Body . Close ( )
2023-01-07 21:03:51 +05:30
2024-02-27 19:35:13 +05:30
bod , err := io . ReadAll ( resp . Body )
2023-02-05 19:00:47 +05:30
if err != nil {
2023-07-11 02:53:29 +05:30
log . Error ( "Error reading captcha response body" , err )
2023-02-05 19:00:47 +05:30
}
2023-07-11 02:53:29 +05:30
sb := string ( bod )
log . Info ( "Captcha response: " , sb )
type CaptchaResponse struct {
Success bool ` json:"success" `
}
var captchaResponse CaptchaResponse
err = json . Unmarshal ( [ ] byte ( sb ) , & captchaResponse )
2023-01-07 21:32:06 +05:30
if err != nil {
2023-07-11 02:53:29 +05:30
log . Error ( "Error unmarshalling captcha response" , err )
2023-01-07 21:32:06 +05:30
}
2023-01-07 21:03:51 +05:30
2023-07-11 02:53:29 +05:30
if captchaResponse . Success == false {
log . Error ( "Captcha validation failed" )
2023-07-11 03:38:46 +05:30
return c . JSON ( fiber . Map {
"username" : username ,
"message" : "Sorry! But the captcha validation failed. Please try again." ,
"status" : c . Response ( ) . StatusCode ( ) ,
} )
2023-07-11 02:53:29 +05:30
} else {
2024-02-27 19:35:13 +05:30
// Check if user already exists
// We'll check the home folder and see if the username folder exists.
_ , err := os . Stat ( "/home/" + username )
if err == nil {
log . Error ( "User already exists" , username )
return c . JSON ( fiber . Map {
"username" : username ,
"message" : "User already exists, Choose a different username." ,
"status" : c . Response ( ) . StatusCode ( ) ,
} )
}
2024-02-27 19:37:27 +05:30
2023-07-11 02:53:29 +05:30
// create user file
f , err := os . Create ( "/var/publapi/users/" + 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 )
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 )
// write to file
_ , 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" ,
)
// send notification to user that their reg request was sent
2023-08-13 15:58:34 +05:30
// err = shoutrrr.Send(os.Getenv("PUBLAPI_EMAIL_SHOUTRRRURL")+email, "Hello "+username+",\nYour registration request has been sent.\nIt will take a maximum of 48 hours for the request to be processed.\nThank you for being part of the Project Segfault Pubnix.")
// if err != nil {
// log.Error("Error sending email to user", err)
// return c.SendStatus(fiber.StatusInternalServerError)
// }
2023-07-11 02:53:29 +05:30
// send notification to admins
2023-08-13 15:58:34 +05:30
shoutrrrUrl := os . Getenv ( "PUBLAPI_NOTIFY_SHOUTRRRURL" ) + os . Getenv ( "PUBLAPI_NOTIFY_ROOMS" )
2023-07-11 02:53:29 +05:30
err = shoutrrr . Send (
shoutrrrUrl ,
"New user signup! Please review /var/publapi/users/" + username + ".sh to approve or deny the user. IP: " + ip + " Email: " + email ,
)
if err != nil {
log . Error ( "Error sending notification to admins" , err )
return c . SendStatus ( fiber . StatusInternalServerError )
}
return c . JSON ( fiber . Map {
"username" : username ,
"message" : "User created! Please allow us 24 hours or more to review your account." ,
"status" : c . Response ( ) . StatusCode ( ) ,
} )
}
2023-01-07 21:03:51 +05:30
}