mirror of
https://github.com/hrfee/jfa-go.git
synced 2024-12-22 17:10:10 +00:00
pwr: functioning captcha/recaptcha
This commit is contained in:
parent
ab05c07469
commit
278588ca39
@ -503,7 +503,7 @@ func (app *appContext) NewUser(gc *gin.Context) {
|
|||||||
var req newUserDTO
|
var req newUserDTO
|
||||||
gc.BindJSON(&req)
|
gc.BindJSON(&req)
|
||||||
app.debug.Printf("%s: New user attempt", req.Code)
|
app.debug.Printf("%s: New user attempt", req.Code)
|
||||||
if app.config.Section("captcha").Key("enabled").MustBool(false) && !app.verifyCaptcha(req.Code, req.CaptchaID, req.CaptchaText) {
|
if app.config.Section("captcha").Key("enabled").MustBool(false) && !app.verifyCaptcha(req.Code, req.CaptchaID, req.CaptchaText, false) {
|
||||||
app.info.Printf("%s: New user failed: Captcha Incorrect", req.Code)
|
app.info.Printf("%s: New user failed: Captcha Incorrect", req.Code)
|
||||||
respond(400, "errorCaptcha", gc)
|
respond(400, "errorCaptcha", gc)
|
||||||
return
|
return
|
||||||
|
10
api.go
10
api.go
@ -114,6 +114,7 @@ func (app *appContext) ResetSetPassword(gc *gin.Context) {
|
|||||||
var req ResetPasswordDTO
|
var req ResetPasswordDTO
|
||||||
gc.BindJSON(&req)
|
gc.BindJSON(&req)
|
||||||
validation := app.validator.validate(req.Password)
|
validation := app.validator.validate(req.Password)
|
||||||
|
captcha := app.config.Section("captcha").Key("enabled").MustBool(false)
|
||||||
valid := true
|
valid := true
|
||||||
for _, val := range validation {
|
for _, val := range validation {
|
||||||
if !val {
|
if !val {
|
||||||
@ -121,12 +122,18 @@ func (app *appContext) ResetSetPassword(gc *gin.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !valid || req.PIN == "" {
|
if !valid || req.PIN == "" {
|
||||||
// 200 bcs idk what i did in js
|
|
||||||
app.info.Printf("%s: Password reset failed: Invalid password", req.PIN)
|
app.info.Printf("%s: Password reset failed: Invalid password", req.PIN)
|
||||||
gc.JSON(400, validation)
|
gc.JSON(400, validation)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
isInternal := false
|
isInternal := false
|
||||||
|
|
||||||
|
if captcha && !app.verifyCaptcha(req.PIN, req.PIN, req.CaptchaText, true) {
|
||||||
|
app.info.Printf("%s: PWR Failed: Captcha Incorrect", req.PIN)
|
||||||
|
respond(400, "errorCaptcha", gc)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
var userID, username string
|
var userID, username string
|
||||||
if reset, ok := app.internalPWRs[req.PIN]; ok {
|
if reset, ok := app.internalPWRs[req.PIN]; ok {
|
||||||
isInternal = true
|
isInternal = true
|
||||||
@ -138,6 +145,7 @@ func (app *appContext) ResetSetPassword(gc *gin.Context) {
|
|||||||
}
|
}
|
||||||
userID = reset.ID
|
userID = reset.ID
|
||||||
username = reset.Username
|
username = reset.Username
|
||||||
|
|
||||||
status, err := app.jf.ResetPasswordAdmin(userID)
|
status, err := app.jf.ResetPasswordAdmin(userID)
|
||||||
if !(status == 200 || status == 204) || err != nil {
|
if !(status == 200 || status == 204) || err != nil {
|
||||||
app.err.Printf("Password Reset failed (%d): %v", status, err)
|
app.err.Printf("Password Reset failed (%d): %v", status, err)
|
||||||
|
@ -34,8 +34,12 @@
|
|||||||
</script>
|
</script>
|
||||||
{{ if .passwordReset }}
|
{{ if .passwordReset }}
|
||||||
<script src="js/pwr.js" type="module"></script>
|
<script src="js/pwr.js" type="module"></script>
|
||||||
|
<script>
|
||||||
|
window.pwrPIN = "{{ .pwrPIN }}";
|
||||||
|
</script>
|
||||||
{{ else }}
|
{{ else }}
|
||||||
<script src="js/form.js" type="module"></script>
|
<script src="js/form.js" type="module"></script>
|
||||||
|
{{ end }}
|
||||||
{{ if .reCAPTCHA }}
|
{{ if .reCAPTCHA }}
|
||||||
<script>
|
<script>
|
||||||
var reCAPTCHACallback = () => {
|
var reCAPTCHACallback = () => {
|
||||||
@ -49,4 +53,3 @@
|
|||||||
<script src="https://www.google.com/recaptcha/api.js?onload=reCAPTCHACallback&render=explicit" async defer></script>
|
<script src="https://www.google.com/recaptcha/api.js?onload=reCAPTCHACallback&render=explicit" async defer></script>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
{{ end }}
|
|
||||||
|
1
main.go
1
main.go
@ -120,6 +120,7 @@ type appContext struct {
|
|||||||
proxyTransport *http.Transport
|
proxyTransport *http.Transport
|
||||||
proxyConfig easyproxy.ProxyConfig
|
proxyConfig easyproxy.ProxyConfig
|
||||||
internalPWRs map[string]InternalPWR
|
internalPWRs map[string]InternalPWR
|
||||||
|
pwrCaptchas map[string]Captcha
|
||||||
ConfirmationKeys map[string]map[string]newUserDTO // Map of invite code to jwt to request
|
ConfirmationKeys map[string]map[string]newUserDTO // Map of invite code to jwt to request
|
||||||
confirmationKeysLock sync.Mutex
|
confirmationKeysLock sync.Mutex
|
||||||
}
|
}
|
||||||
|
@ -332,8 +332,9 @@ type MatrixLoginDTO struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ResetPasswordDTO struct {
|
type ResetPasswordDTO struct {
|
||||||
PIN string `json:"pin"`
|
PIN string `json:"pin"`
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
|
CaptchaText string `json:"captcha_text"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type AdminPasswordResetDTO struct {
|
type AdminPasswordResetDTO struct {
|
||||||
|
19
ts/form.ts
19
ts/form.ts
@ -4,7 +4,7 @@ import { _get, _post, toggleLoader, addLoader, removeLoader, toDateString } from
|
|||||||
import { loadLangSelector } from "./modules/lang.js";
|
import { loadLangSelector } from "./modules/lang.js";
|
||||||
import { Validator, ValidatorConf, ValidatorRespDTO } from "./modules/validator.js";
|
import { Validator, ValidatorConf, ValidatorRespDTO } from "./modules/validator.js";
|
||||||
import { Discord, Telegram, Matrix, ServiceConfiguration, MatrixConfiguration } from "./modules/account-linking.js";
|
import { Discord, Telegram, Matrix, ServiceConfiguration, MatrixConfiguration } from "./modules/account-linking.js";
|
||||||
import { Captcha } from "./modules/captcha.js";
|
import { Captcha, GreCAPTCHA } from "./modules/captcha.js";
|
||||||
|
|
||||||
interface formWindow extends Window {
|
interface formWindow extends Window {
|
||||||
invalidPassword: string;
|
invalidPassword: string;
|
||||||
@ -173,7 +173,7 @@ if (!window.usernameEnabled) { usernameField.parentElement.remove(); usernameFie
|
|||||||
const passwordField = document.getElementById("create-password") as HTMLInputElement;
|
const passwordField = document.getElementById("create-password") as HTMLInputElement;
|
||||||
const rePasswordField = document.getElementById("create-reenter-password") as HTMLInputElement;
|
const rePasswordField = document.getElementById("create-reenter-password") as HTMLInputElement;
|
||||||
|
|
||||||
let captcha = new Captcha(window.code, window.captcha, window.reCAPTCHA);
|
let captcha = new Captcha(window.code, window.captcha, window.reCAPTCHA, false);
|
||||||
|
|
||||||
function _baseValidator(oncomplete: (valid: boolean) => void, captchaValid: boolean): void {
|
function _baseValidator(oncomplete: (valid: boolean) => void, captchaValid: boolean): void {
|
||||||
if (window.emailRequired) {
|
if (window.emailRequired) {
|
||||||
@ -203,20 +203,7 @@ function _baseValidator(oncomplete: (valid: boolean) => void, captchaValid: bool
|
|||||||
|
|
||||||
let baseValidator = captcha.baseValidatorWrapper(_baseValidator);
|
let baseValidator = captcha.baseValidatorWrapper(_baseValidator);
|
||||||
|
|
||||||
interface GreCAPTCHA {
|
declare var grecaptcha: GreCAPTCHA;
|
||||||
render: (container: HTMLDivElement, parameters: {
|
|
||||||
sitekey?: string,
|
|
||||||
theme?: string,
|
|
||||||
size?: string,
|
|
||||||
tabindex?: number,
|
|
||||||
"callback"?: () => void,
|
|
||||||
"expired-callback"?: () => void,
|
|
||||||
"error-callback"?: () => void
|
|
||||||
}) => void;
|
|
||||||
getResponse: (opt_widget_id?: HTMLDivElement) => string;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare var grecaptcha: GreCAPTCHA
|
|
||||||
|
|
||||||
let validatorConf: ValidatorConf = {
|
let validatorConf: ValidatorConf = {
|
||||||
passwordField: passwordField,
|
passwordField: passwordField,
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { _get, _post } from "./common.js";
|
import { _get, _post } from "./common.js";
|
||||||
|
|
||||||
export class Captcha {
|
export class Captcha {
|
||||||
|
isPWR = false;
|
||||||
enabled = true;
|
enabled = true;
|
||||||
verified = false;
|
verified = false;
|
||||||
captchaID = "";
|
captchaID = "";
|
||||||
@ -27,7 +28,7 @@ export class Captcha {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
verify = (callback: () => void) => _post("/captcha/verify/" + this.code + "/" + this.captchaID + "/" + this.input.value, null, (req: XMLHttpRequest) => {
|
verify = (callback: () => void) => _post("/captcha/verify/" + this.code + "/" + this.captchaID + "/" + this.input.value + (this.isPWR ? "?pwr=true" : ""), null, (req: XMLHttpRequest) => {
|
||||||
if (req.readyState == 4) {
|
if (req.readyState == 4) {
|
||||||
if (req.status == 204) {
|
if (req.status == 204) {
|
||||||
this.checkbox.innerHTML = `<i class="ri-check-line"></i>`;
|
this.checkbox.innerHTML = `<i class="ri-check-line"></i>`;
|
||||||
@ -44,21 +45,37 @@ export class Captcha {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
generate = () => _get("/captcha/gen/"+this.code, null, (req: XMLHttpRequest) => {
|
generate = () => _get("/captcha/gen/"+this.code+(this.isPWR ? "?pwr=true" : ""), null, (req: XMLHttpRequest) => {
|
||||||
if (req.readyState == 4) {
|
if (req.readyState == 4) {
|
||||||
if (req.status == 200) {
|
if (req.status == 200) {
|
||||||
this.captchaID = req.response["id"];
|
this.captchaID = this.isPWR ? this.code : req.response["id"];
|
||||||
|
// the Math.random() appearance below is used for PWRs, since they don't have a unique captchaID. The parameter is ignored by the server, but tells the browser to reload the image.
|
||||||
document.getElementById("captcha-img").innerHTML = `
|
document.getElementById("captcha-img").innerHTML = `
|
||||||
<img class="w-100" src="${window.location.toString().substring(0, window.location.toString().lastIndexOf("/invite"))}/captcha/img/${this.code}/${this.captchaID}"></img>
|
<img class="w-100" src="${window.location.toString().substring(0, window.location.toString().lastIndexOf("/invite"))}/captcha/img/${this.code}/${this.isPWR ? Math.random() : this.captchaID}${this.isPWR ? "?pwr=true" : ""}"></img>
|
||||||
`;
|
`;
|
||||||
this.input.value = "";
|
this.input.value = "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
constructor(code: string, enabled: boolean, reCAPTCHA: boolean) {
|
constructor(code: string, enabled: boolean, reCAPTCHA: boolean, isPWR: boolean) {
|
||||||
this.code = code;
|
this.code = code;
|
||||||
this.enabled = enabled;
|
this.enabled = enabled;
|
||||||
this.reCAPTCHA = reCAPTCHA;
|
this.reCAPTCHA = reCAPTCHA;
|
||||||
|
this.isPWR = isPWR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface GreCAPTCHA {
|
||||||
|
render: (container: HTMLDivElement, parameters: {
|
||||||
|
sitekey?: string,
|
||||||
|
theme?: string,
|
||||||
|
size?: string,
|
||||||
|
tabindex?: number,
|
||||||
|
"callback"?: () => void,
|
||||||
|
"expired-callback"?: () => void,
|
||||||
|
"error-callback"?: () => void
|
||||||
|
}) => void;
|
||||||
|
getResponse: (opt_widget_id?: HTMLDivElement) => string;
|
||||||
|
}
|
||||||
|
|
||||||
|
49
ts/pwr.ts
49
ts/pwr.ts
@ -2,6 +2,7 @@ import { Modal } from "./modules/modal.js";
|
|||||||
import { Validator, ValidatorConf } from "./modules/validator.js";
|
import { Validator, ValidatorConf } from "./modules/validator.js";
|
||||||
import { _post, addLoader, removeLoader } from "./modules/common.js";
|
import { _post, addLoader, removeLoader } from "./modules/common.js";
|
||||||
import { loadLangSelector } from "./modules/lang.js";
|
import { loadLangSelector } from "./modules/lang.js";
|
||||||
|
import { Captcha, GreCAPTCHA } from "./modules/captcha.js";
|
||||||
|
|
||||||
interface formWindow extends Window {
|
interface formWindow extends Window {
|
||||||
invalidPassword: string;
|
invalidPassword: string;
|
||||||
@ -31,6 +32,7 @@ interface formWindow extends Window {
|
|||||||
captcha: boolean;
|
captcha: boolean;
|
||||||
reCAPTCHA: boolean;
|
reCAPTCHA: boolean;
|
||||||
reCAPTCHASiteKey: string;
|
reCAPTCHASiteKey: string;
|
||||||
|
pwrPIN: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
loadLangSelector("pwr");
|
loadLangSelector("pwr");
|
||||||
@ -45,11 +47,26 @@ const rePasswordField = document.getElementById("create-reenter-password") as HT
|
|||||||
|
|
||||||
window.successModal = new Modal(document.getElementById("modal-success"), true);
|
window.successModal = new Modal(document.getElementById("modal-success"), true);
|
||||||
|
|
||||||
|
function _baseValidator(oncomplete: (valid: boolean) => void, captchaValid: boolean): void {
|
||||||
|
if (window.captcha && !window.reCAPTCHA && !captchaValid) {
|
||||||
|
oncomplete(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
oncomplete(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
let captcha = new Captcha(window.pwrPIN, window.captcha, window.reCAPTCHA, true);
|
||||||
|
|
||||||
|
declare var grecaptcha: GreCAPTCHA;
|
||||||
|
|
||||||
|
let baseValidator = captcha.baseValidatorWrapper(_baseValidator);
|
||||||
|
|
||||||
let validatorConf: ValidatorConf = {
|
let validatorConf: ValidatorConf = {
|
||||||
passwordField: passwordField,
|
passwordField: passwordField,
|
||||||
rePasswordField: rePasswordField,
|
rePasswordField: rePasswordField,
|
||||||
submitInput: submitInput,
|
submitInput: submitInput,
|
||||||
submitButton: submitSpan
|
submitButton: submitSpan,
|
||||||
|
validatorFunc: baseValidator
|
||||||
};
|
};
|
||||||
|
|
||||||
var validator = new Validator(validatorConf);
|
var validator = new Validator(validatorConf);
|
||||||
@ -58,6 +75,13 @@ var requirements = validator.requirements;
|
|||||||
interface sendDTO {
|
interface sendDTO {
|
||||||
pin: string;
|
pin: string;
|
||||||
password: string;
|
password: string;
|
||||||
|
captcha_text?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window.captcha && !window.reCAPTCHA) {
|
||||||
|
captcha.generate();
|
||||||
|
(document.getElementById("captcha-regen") as HTMLSpanElement).onclick = captcha.generate;
|
||||||
|
captcha.input.onkeyup = validator.validate;
|
||||||
}
|
}
|
||||||
|
|
||||||
form.onsubmit = (event: Event) => {
|
form.onsubmit = (event: Event) => {
|
||||||
@ -68,12 +92,31 @@ form.onsubmit = (event: Event) => {
|
|||||||
pin: params.get("pin"),
|
pin: params.get("pin"),
|
||||||
password: passwordField.value
|
password: passwordField.value
|
||||||
};
|
};
|
||||||
|
if (window.captcha) {
|
||||||
|
if (window.reCAPTCHA) {
|
||||||
|
send.captcha_text = grecaptcha.getResponse();
|
||||||
|
} else {
|
||||||
|
send.captcha_text = captcha.input.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
_post("/reset", send, (req: XMLHttpRequest) => {
|
_post("/reset", send, (req: XMLHttpRequest) => {
|
||||||
if (req.readyState == 4) {
|
if (req.readyState == 4) {
|
||||||
removeLoader(submitSpan);
|
removeLoader(submitSpan);
|
||||||
if (req.status == 400) {
|
if (req.status == 400) {
|
||||||
for (let type in req.response) {
|
if (req.response["error"] as string) { // FIXME: Show captcha error
|
||||||
if (requirements[type]) { requirements[type].valid = req.response[type] as boolean; }
|
const old = submitSpan.textContent;
|
||||||
|
submitSpan.textContent = window.messages[req.response["error"]];
|
||||||
|
submitSpan.classList.add("~critical");
|
||||||
|
submitSpan.classList.remove("~urge");
|
||||||
|
setTimeout(() => {
|
||||||
|
submitSpan.classList.add("~urge");
|
||||||
|
submitSpan.classList.remove("~critical");
|
||||||
|
submitSpan.textContent = old;
|
||||||
|
}, 2000);
|
||||||
|
} else {
|
||||||
|
for (let type in req.response) {
|
||||||
|
if (requirements[type]) { requirements[type].valid = req.response[type] as boolean; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} else if (req.status != 200) {
|
} else if (req.status != 200) {
|
||||||
|
115
views.go
115
views.go
@ -299,6 +299,7 @@ func (app *appContext) ResetPassword(gc *gin.Context) {
|
|||||||
data["captcha"] = app.config.Section("captcha").Key("enabled").MustBool(false)
|
data["captcha"] = app.config.Section("captcha").Key("enabled").MustBool(false)
|
||||||
data["reCAPTCHA"] = app.config.Section("captcha").Key("recaptcha").MustBool(false)
|
data["reCAPTCHA"] = app.config.Section("captcha").Key("recaptcha").MustBool(false)
|
||||||
data["reCAPTCHASiteKey"] = app.config.Section("captcha").Key("recaptcha_site_key").MustString("")
|
data["reCAPTCHASiteKey"] = app.config.Section("captcha").Key("recaptcha_site_key").MustString("")
|
||||||
|
data["pwrPIN"] = pin
|
||||||
gcHTML(gc, http.StatusOK, "form-loader.html", data)
|
gcHTML(gc, http.StatusOK, "form-loader.html", data)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -396,20 +397,28 @@ func (app *appContext) ResetPassword(gc *gin.Context) {
|
|||||||
// @Router /captcha/img/{code}/{captchaID} [get]
|
// @Router /captcha/img/{code}/{captchaID} [get]
|
||||||
func (app *appContext) GetCaptcha(gc *gin.Context) {
|
func (app *appContext) GetCaptcha(gc *gin.Context) {
|
||||||
code := gc.Param("invCode")
|
code := gc.Param("invCode")
|
||||||
|
isPWR := gc.Query("pwr") == "true"
|
||||||
captchaID := gc.Param("captchaID")
|
captchaID := gc.Param("captchaID")
|
||||||
inv, ok := app.storage.GetInvitesKey(code)
|
var inv Invite
|
||||||
if !ok {
|
|
||||||
gcHTML(gc, 404, "invalidCode.html", gin.H{
|
|
||||||
"urlBase": app.getURLBase(gc),
|
|
||||||
"cssClass": app.cssClass,
|
|
||||||
"cssVersion": cssVersion,
|
|
||||||
"contactMessage": app.config.Section("ui").Key("contact_message").String(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
var capt Captcha
|
var capt Captcha
|
||||||
ok = true
|
ok := true
|
||||||
if inv.Captchas != nil {
|
if !isPWR {
|
||||||
capt, ok = inv.Captchas[captchaID]
|
inv, ok = app.storage.GetInvitesKey(code)
|
||||||
|
if !ok {
|
||||||
|
gcHTML(gc, 404, "invalidCode.html", gin.H{
|
||||||
|
"urlBase": app.getURLBase(gc),
|
||||||
|
"cssClass": app.cssClass,
|
||||||
|
"cssVersion": cssVersion,
|
||||||
|
"contactMessage": app.config.Section("ui").Key("contact_message").String(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if inv.Captchas != nil {
|
||||||
|
capt, ok = inv.Captchas[captchaID]
|
||||||
|
} else {
|
||||||
|
ok = false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
capt, ok = app.pwrCaptchas[code]
|
||||||
}
|
}
|
||||||
if !ok {
|
if !ok {
|
||||||
respondBool(400, false, gc)
|
respondBool(400, false, gc)
|
||||||
@ -428,7 +437,13 @@ func (app *appContext) GetCaptcha(gc *gin.Context) {
|
|||||||
// @tags Users
|
// @tags Users
|
||||||
func (app *appContext) GenCaptcha(gc *gin.Context) {
|
func (app *appContext) GenCaptcha(gc *gin.Context) {
|
||||||
code := gc.Param("invCode")
|
code := gc.Param("invCode")
|
||||||
inv, ok := app.storage.GetInvitesKey(code)
|
isPWR := gc.Query("pwr") == "true"
|
||||||
|
var inv Invite
|
||||||
|
ok := true
|
||||||
|
if !isPWR {
|
||||||
|
inv, ok = app.storage.GetInvitesKey(code)
|
||||||
|
}
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
gcHTML(gc, 404, "invalidCode.html", gin.H{
|
gcHTML(gc, 404, "invalidCode.html", gin.H{
|
||||||
"urlBase": app.getURLBase(gc),
|
"urlBase": app.getURLBase(gc),
|
||||||
@ -443,7 +458,7 @@ func (app *appContext) GenCaptcha(gc *gin.Context) {
|
|||||||
respondBool(500, false, gc)
|
respondBool(500, false, gc)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if inv.Captchas == nil {
|
if !isPWR && inv.Captchas == nil {
|
||||||
inv.Captchas = map[string]Captcha{}
|
inv.Captchas = map[string]Captcha{}
|
||||||
}
|
}
|
||||||
captchaID := genAuthToken()
|
captchaID := genAuthToken()
|
||||||
@ -453,26 +468,43 @@ func (app *appContext) GenCaptcha(gc *gin.Context) {
|
|||||||
respondBool(500, false, gc)
|
respondBool(500, false, gc)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
inv.Captchas[captchaID] = Captcha{
|
if isPWR {
|
||||||
Answer: capt.Text,
|
if app.pwrCaptchas == nil {
|
||||||
Image: buf.Bytes(),
|
app.pwrCaptchas = map[string]Captcha{}
|
||||||
Generated: time.Now(),
|
}
|
||||||
|
app.pwrCaptchas[code] = Captcha{
|
||||||
|
Answer: capt.Text,
|
||||||
|
Image: buf.Bytes(),
|
||||||
|
Generated: time.Now(),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
inv.Captchas[captchaID] = Captcha{
|
||||||
|
Answer: capt.Text,
|
||||||
|
Image: buf.Bytes(),
|
||||||
|
Generated: time.Now(),
|
||||||
|
}
|
||||||
|
app.storage.SetInvitesKey(code, inv)
|
||||||
}
|
}
|
||||||
app.storage.SetInvitesKey(code, inv)
|
|
||||||
gc.JSON(200, genCaptchaDTO{captchaID})
|
gc.JSON(200, genCaptchaDTO{captchaID})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (app *appContext) verifyCaptcha(code, id, text string) bool {
|
func (app *appContext) verifyCaptcha(code, id, text string, isPWR bool) bool {
|
||||||
reCAPTCHA := app.config.Section("captcha").Key("recaptcha").MustBool(false)
|
reCAPTCHA := app.config.Section("captcha").Key("recaptcha").MustBool(false)
|
||||||
if !reCAPTCHA {
|
if !reCAPTCHA {
|
||||||
// internal CAPTCHA
|
// internal CAPTCHA
|
||||||
inv, ok := app.storage.GetInvitesKey(code)
|
var c Captcha
|
||||||
if !ok || inv.Captchas == nil {
|
ok := true
|
||||||
app.debug.Printf("Couldn't find invite \"%s\"", code)
|
if !isPWR {
|
||||||
return false
|
inv, ok := app.storage.GetInvitesKey(code)
|
||||||
|
if !ok || (!isPWR && inv.Captchas == nil) {
|
||||||
|
app.debug.Printf("Couldn't find invite \"%s\"", code)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
c, ok = inv.Captchas[id]
|
||||||
|
} else {
|
||||||
|
c, ok = app.pwrCaptchas[code]
|
||||||
}
|
}
|
||||||
c, ok := inv.Captchas[id]
|
|
||||||
if !ok {
|
if !ok {
|
||||||
app.debug.Printf("Couldn't find Captcha \"%s\"", id)
|
app.debug.Printf("Couldn't find Captcha \"%s\"", id)
|
||||||
return false
|
return false
|
||||||
@ -532,21 +564,30 @@ func (app *appContext) verifyCaptcha(code, id, text string) bool {
|
|||||||
// @Router /captcha/verify/{code}/{captchaID}/{text} [get]
|
// @Router /captcha/verify/{code}/{captchaID}/{text} [get]
|
||||||
func (app *appContext) VerifyCaptcha(gc *gin.Context) {
|
func (app *appContext) VerifyCaptcha(gc *gin.Context) {
|
||||||
code := gc.Param("invCode")
|
code := gc.Param("invCode")
|
||||||
|
isPWR := gc.Query("pwr") == "true"
|
||||||
captchaID := gc.Param("captchaID")
|
captchaID := gc.Param("captchaID")
|
||||||
text := gc.Param("text")
|
text := gc.Param("text")
|
||||||
inv, ok := app.storage.GetInvitesKey(code)
|
var inv Invite
|
||||||
if !ok {
|
|
||||||
gcHTML(gc, 404, "invalidCode.html", gin.H{
|
|
||||||
"urlBase": app.getURLBase(gc),
|
|
||||||
"cssClass": app.cssClass,
|
|
||||||
"cssVersion": cssVersion,
|
|
||||||
"contactMessage": app.config.Section("ui").Key("contact_message").String(),
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var capt Captcha
|
var capt Captcha
|
||||||
if inv.Captchas != nil {
|
var ok bool
|
||||||
capt, ok = inv.Captchas[captchaID]
|
if !isPWR {
|
||||||
|
inv, ok = app.storage.GetInvitesKey(code)
|
||||||
|
if !ok {
|
||||||
|
gcHTML(gc, 404, "invalidCode.html", gin.H{
|
||||||
|
"urlBase": app.getURLBase(gc),
|
||||||
|
"cssClass": app.cssClass,
|
||||||
|
"cssVersion": cssVersion,
|
||||||
|
"contactMessage": app.config.Section("ui").Key("contact_message").String(),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if inv.Captchas != nil {
|
||||||
|
capt, ok = inv.Captchas[captchaID]
|
||||||
|
} else {
|
||||||
|
ok = false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
capt, ok = app.pwrCaptchas[code]
|
||||||
}
|
}
|
||||||
if !ok {
|
if !ok {
|
||||||
respondBool(400, false, gc)
|
respondBool(400, false, gc)
|
||||||
|
Loading…
Reference in New Issue
Block a user