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
)
2024-09-29 00:20:57 +05:30
type formValues struct {
Username string
Email string
SshPublicKey string
IPAddress string
CaptchaResponse string
}
type CaptchaResponse struct {
Success bool ` json:"success" `
}
2023-07-11 02:53:29 +05:30
2024-09-29 00:20:57 +05:30
// SignupPage is the signup page handler
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" )
2024-09-29 00:20:57 +05:30
if SignupIPExists {
2023-02-18 15:20:24 +05:30
if c . IP ( ) != SignupIP {
log . Info ( "Request made from invalid IP: " , c . IP ( ) )
return c . SendStatus ( fiber . StatusForbidden )
}
}
2023-07-11 02:53:29 +05:30
2024-09-29 00:20:57 +05:30
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 == "" {
2023-07-11 02:53:29 +05:30
log . Error ( "Nice try, but the registration won't work unless you answer the captcha." )
return c . SendStatus ( fiber . StatusBadRequest )
}
2024-09-29 00:20:57 +05:30
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 )
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: " ,
2024-09-29 00:20:57 +05:30
formValues . Username ,
2023-07-11 02:53:29 +05:30
" " ,
2024-09-29 00:20:57 +05:30
formValues . Email ,
2023-07-11 02:53:29 +05:30
" " ,
2024-09-29 00:20:57 +05:30
formValues . IPAddress ,
2023-07-11 02:53:29 +05:30
" " ,
)
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.
2024-09-29 00:20:57 +05:30
captchaSecret , _ := os . LookupEnv ( "PUBLAPI_CAPTCHA_SECRET" )
2023-07-11 02:53:29 +05:30
params := url . Values { }
2024-09-29 00:20:57 +05:30
params . Add ( "response" , formValues . CaptchaResponse )
2023-07-11 02:53:29 +05:30
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 )
2024-09-29 00:20:57 +05:30
captchaResponse := CaptchaResponse { }
2023-07-11 02:53:29 +05:30
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
2024-09-29 00:20:57 +05:30
if ! captchaResponse . Success {
2023-07-11 02:53:29 +05:30
log . Error ( "Captcha validation failed" )
2023-07-11 03:38:46 +05:30
return c . JSON ( fiber . Map {
2024-09-29 00:20:57 +05:30
"username" : formValues . CaptchaResponse ,
"message" : "Sorry, but the captcha validation failed. Please try again." ,
2023-07-11 03:38:46 +05:30
"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.
2024-09-29 00:20:57 +05:30
_ , err := os . Stat ( "/home/" + formValues . Username )
2024-02-27 19:35:13 +05:30
if err == nil {
2024-09-29 00:20:57 +05:30
log . Error ( "User already exists : " , formValues . Username )
2024-02-27 19:35:13 +05:30
return c . JSON ( fiber . Map {
2024-09-29 00:20:57 +05:30
"username" : formValues . Username ,
2024-02-27 19:59:50 +05:30
"message" : "User already exists. Please choose a different username." ,
2024-02-27 19:35:13 +05:30
"status" : c . Response ( ) . StatusCode ( ) ,
} )
}
2024-02-27 19:37:27 +05:30
2023-07-11 02:53:29 +05:30
// create user file
2024-09-29 00:20:57 +05:30
f , err := os . Create ( "/var/publapi/users/" + formValues . Username + ".sh" )
2023-07-11 02:53:29 +05:30
if err != nil {
log . Error ( "Error creating user file" , err )
return c . SendStatus ( fiber . StatusInternalServerError )
}
defer f . Close ( )
2024-09-29 00:20:57 +05:30
chmoderr := os . Chmod ( "/var/publapi/users/" + formValues . Username + ".sh" , 0700 )
2023-07-11 02:53:29 +05:30
if chmoderr != nil {
log . Error ( err )
}
2024-09-29 00:20:57 +05:30
bashScript := strings . ReplaceAll ( utils . BashScript , "{{sshkey}}" , formValues . SshPublicKey )
bashScript = strings . ReplaceAll ( bashScript , "{{email}}" , formValues . Email )
bashScript = strings . ReplaceAll ( bashScript , "{{username}}" , formValues . Username )
2023-07-11 02:53:29 +05:30
// write to file
2024-09-29 00:20:57 +05:30
_ , err = f . WriteString ( bashScript )
2023-07-11 02:53:29 +05:30
if err != nil {
log . Error ( "Error writing to user file" , err )
return c . SendStatus ( fiber . StatusInternalServerError )
}
log . Info (
2024-09-29 00:20:57 +05:30
"Registration request for " + formValues . Username + " has been submitted by the frontend and has been written to /var/publapi/users/" + formValues . Username + ".sh" ,
2023-07-11 02:53:29 +05:30
)
// 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 ,
2024-09-29 00:20:57 +05:30
"New user signup! Please review /var/publapi/users/" + formValues . Username + ".sh to approve or deny the user. IP: " + formValues . IPAddress + " Email: " + formValues . Email ,
2023-07-11 02:53:29 +05:30
)
if err != nil {
log . Error ( "Error sending notification to admins" , err )
2024-05-22 11:16:10 +05:30
//return c.SendStatus(fiber.StatusInternalServerError)
2023-07-11 02:53:29 +05:30
}
return c . JSON ( fiber . Map {
2024-09-29 00:20:57 +05:30
"username" : formValues . Username ,
2023-07-11 02:53:29 +05:30
"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
}