bsw/jbe@1309: local function check_italian_mobile_phone_number(value) bsw/jbe@1309: bsw/jbe@1309: if not value then bsw/jbe@1309: return false bsw/jbe@1309: end bsw/jbe@1309: bsw/jbe@1309: value = string.gsub(value, "[^0-9]*", "") bsw/jbe@1309: bsw/jbe@1309: if #(value) < 9 or #(value) > 10 then bsw/jbe@1309: return false bsw/jbe@1309: end bsw/jbe@1309: bsw/jbe@1309: local mobile_phone_prefixes = { bsw/jbe@1309: { min = 320, max = 329, comment = "Wind Tre" }, bsw/jbe@1309: { min = 330, max = 339, comment = "Telecom Italia (TIM)" }, bsw/jbe@1309: { min = 340, max = 349, comment = "Vodafone Omnitel" }, bsw/jbe@1309: { min = 350, max = 359, comment = "" }, bsw/jbe@1309: { min = 360, max = 369, comment = "Telecom Italia (TIM)" }, bsw/jbe@1309: { min = 370, max = 379, comment = "" }, bsw/jbe@1309: { min = 380, max = 389, comment = "Wind Tre" }, bsw/jbe@1309: { min = 390, max = 393, comment = "Wind Tre" }, bsw/jbe@1309: { min = 394, max = 399, comment = "Wind Tre" } bsw/jbe@1309: } bsw/jbe@1309: bsw/jbe@1309: local value_prefix = tonumber(string.match(value, "^(...)")) bsw/jbe@1309: bsw/jbe@1309: local valid_prefix = false bsw/jbe@1309: bsw/jbe@1309: for i, prefix in ipairs(mobile_phone_prefixes) do bsw/jbe@1309: trace.debug(value_prefix, prefix.min) bsw/jbe@1309: if value_prefix >= prefix.min and value_prefix <= prefix.max then bsw/jbe@1309: valid_prefix = true bsw/jbe@1309: end bsw/jbe@1309: end bsw/jbe@1309: bsw/jbe@1309: if valid_prefix then bsw/jbe@1309: return true bsw/jbe@1309: else bsw/jbe@1309: return false bsw/jbe@1309: end bsw/jbe@1309: end bsw/jbe@1309: bsw/jbe@1309: local function check_uk_mobile_phone_number(value) bsw/jbe@1309: bsw/jbe@1309: if not value then bsw/jbe@1309: return false bsw/jbe@1309: end bsw/jbe@1309: bsw/jbe@1309: value = string.gsub(value, "[^0-9]*", "") bsw/jbe@1309: bsw/jbe@1309: if #(value) < 11 or #(value) > 11 then bsw/jbe@1309: return false bsw/jbe@1309: end bsw/jbe@1309: bsw/jbe@1309: local mobile_phone_prefixes = { bsw/jbe@1309: { min = 071, max = 079, comment = "UK phone" }, bsw/jbe@1309: } bsw/jbe@1309: bsw/jbe@1309: local value_prefix = tonumber(string.match(value, "^(...)")) bsw/jbe@1309: bsw/jbe@1309: local valid_prefix = false bsw/jbe@1309: bsw/jbe@1309: for i, prefix in ipairs(mobile_phone_prefixes) do bsw/jbe@1309: trace.debug(value_prefix, prefix.min) bsw/jbe@1309: if value_prefix >= prefix.min and value_prefix <= prefix.max then bsw/jbe@1309: valid_prefix = true bsw/jbe@1309: end bsw/jbe@1309: end bsw/jbe@1309: bsw/jbe@1309: if valid_prefix then bsw/jbe@1309: return true bsw/jbe@1309: else bsw/jbe@1309: return false bsw/jbe@1309: end bsw/jbe@1309: end bsw/jbe@1309: bsw/jbe@1309: local errors = 0 bsw/jbe@1309: bsw/jbe@1309: local manual_verification bsw/jbe@1309: bsw/jbe@1309: if config.self_registration.allow_bypass_checks and param.get("manual_verification") then bsw/jbe@1309: manual_verification = true bsw/jbe@1309: end bsw/jbe@1309: bsw/jbe@1309: for i, checkbox in ipairs(config.use_terms_checkboxes) do bsw/jbe@1309: local accepted = param.get("use_terms_checkbox_" .. checkbox.name, atom.boolean) bsw/jbe@1309: if not accepted then bsw/jbe@1309: slot.put_into("error", checkbox.not_accepted_error) bsw/jbe@1309: errors = errors + 1 bsw/jbe@1309: end bsw/jbe@1309: end bsw/jbe@1309: bsw/jbe@1309: local email = param.get("email") bsw/jbe@1309: bsw/jbe@1309: local members = Member:new_selector() bsw/jbe@1309: :add_where{ "notify_email = ? OR notify_email_unconfirmed = ?", email } bsw/jbe@1309: :exec() bsw/jbe@1309: bsw/jbe@1309: if #members > 0 then bsw/jbe@1309: slot.select("error", function() bsw/jbe@1309: slot.put_into("registration_register_email_invalid", "already_used") bsw/jbe@1309: ui.tag{ content = _"This email address already been used. Please check your inbox for an invitation or contact us." } bsw/jbe@1309: end) bsw/jbe@1309: errors = errors + 1 bsw/jbe@1309: end bsw/jbe@1309: bsw/jbe@1309: local verification = Verification:new() bsw/jbe@1309: verification.requested = "now" bsw/jbe@1309: verification.request_origin = json.object{ bsw/jbe@1309: ip = request.get_header("X-Forwarded-For"), bsw/jbe@1309: hostname = request.get_header("X-Forwarded-Host") bsw/jbe@1309: } bsw/jbe@1309: verification.request_data = json.object() bsw/jbe@1309: bsw/jbe@1309: for i, field in ipairs(config.self_registration.fields) do bsw/jbe@1309: if field.name == "date_of_birth" then bsw/jbe@1309: local day = tonumber(param.get("verification_data_" .. field.name .. "_day")) bsw/jbe@1309: local month = tonumber(param.get("verification_data_" .. field.name .. "_month")) bsw/jbe@1309: local year = tonumber(param.get("verification_data_" .. field.name .. "_year")) bsw/jbe@1309: local date = atom.date:new{ year = year, month = month, day = day } bsw/jbe@1309: if date.invalid then bsw/jbe@1309: slot.select("error", function() bsw/jbe@1309: ui.container{ content = _"Please check date of birth" } bsw/jbe@1309: slot.put_into("self_registration__invalid_" .. field.name, "invalid") bsw/jbe@1309: end) bsw/jbe@1309: errors = errors + 1 bsw/jbe@1309: end bsw/jbe@1309: local today = atom.date:get_current() bsw/jbe@1309: local date_16y_ago = atom.date:new{ year = today.year - 16, month = today.month, day = today.day } bsw/jbe@1309: if date_16y_ago.invalid and today.month == 2 and today.day == 29 then bsw/jbe@1309: date_16y_ago = atom.date:new{ year = today.year - 16, month = 2, day = 28 } bsw/jbe@1309: end bsw/jbe@1309: if date > date_16y_ago then bsw/jbe@1309: request.redirect{ external = encode.url { module = "registration", view = "register_rejected_age" } } bsw/jbe@1309: return bsw/jbe@1309: end bsw/jbe@1309: verification.request_data[field.name] = string.format("%04i-%02i-%02i", year, month, day) bsw/jbe@1309: bsw/jbe@1309: else bsw/jbe@1309: local value = param.get("verification_data_" .. field.name) bsw@1314: if not field.optional and (not value or (#value < 1 and (not manual_verification or field.name ~= "mobile_phone"))) then bsw/jbe@1309: slot.put_into("self_registration__invalid_" .. field.name, "to_short") bsw/jbe@1309: slot.select("error", function() bsw/jbe@1309: ui.container{ content = _("Please enter: #{field_name}", { field_name = field.label }) } bsw/jbe@1309: end) bsw/jbe@1309: errors = errors + 1 bsw/jbe@1309: end bsw/jbe@1309: if field.name == "fiscal_code" then bsw/jbe@1309: value = string.upper(value) bsw/jbe@1309: value = string.gsub(value, "[^A-Z0-9]", "") bsw/jbe@1309: elseif field.name == "mobile_phone" then bsw/jbe@1309: value = string.gsub(value, "[^0-9]", "") bsw/jbe@1309: else bsw/jbe@1309: value = string.gsub(value, "^%s+", "") bsw/jbe@1309: value = string.gsub(value, "%s+$", "") bsw/jbe@1309: value = string.gsub(value, "%s+", " ") bsw/jbe@1309: end bsw/jbe@1309: verification.request_data[field.name] = value bsw/jbe@1309: end bsw/jbe@1309: end bsw/jbe@1309: bsw/jbe@1309: local automatic_verification_possible = true bsw/jbe@1309: bsw/jbe@1309: local mobile_phone = verification.request_data.mobile_phone bsw/jbe@1309: bsw/jbe@1309: if not manual_verification then bsw/jbe@1309: if config.self_registration.check_for_italien_mobile_phone then bsw/jbe@1309: if not check_italian_mobile_phone_number(mobile_phone) then bsw/jbe@1309: slot.select("error", function() bsw/jbe@1309: ui.container{ content = _"Please check the mobile phone number (invalid format)" } bsw/jbe@1309: end) bsw/jbe@1309: errors = errors + 1 bsw/jbe@1309: end bsw/jbe@1309: end bsw/jbe@1309: bsw/jbe@1309: if config.self_registration.check_for_uk_mobile_phone then bsw/jbe@1309: if not check_uk_mobile_phone_number(mobile_phone) then bsw/jbe@1309: slot.select("error", function() bsw/jbe@1309: ui.container{ content = _"Please check the mobile phone number (invalid format)" } bsw/jbe@1309: end) bsw/jbe@1309: errors = errors + 1 bsw/jbe@1309: end bsw/jbe@1309: end bsw/jbe@1309: end bsw/jbe@1309: bsw/jbe@1309: if config.self_registration.check_for_italian_fiscal_code then bsw/jbe@1309: local check_fiscal_code = execute.chunk{ module = "registration", chunk = "_check_fiscal_code" } bsw/jbe@1309: bsw/jbe@1309: local fiscal_code_valid, fiscal_code_error = check_fiscal_code( bsw/jbe@1309: verification.request_data.fiscal_code, bsw/jbe@1309: { bsw/jbe@1309: first_name = verification.request_data.first_name, bsw/jbe@1309: last_name = verification.request_data.name, bsw/jbe@1309: year = tonumber(string.match(verification.request_data.date_of_birth, "^(....)-..-..$")), bsw/jbe@1309: month = tonumber(string.match(verification.request_data.date_of_birth, "^....-(..)-..$")), bsw/jbe@1309: day = tonumber(string.match(verification.request_data.date_of_birth, "^....-..-(..)$")), bsw/jbe@1309: } bsw/jbe@1309: ) bsw/jbe@1309: bsw/jbe@1309: if fiscal_code_valid then bsw/jbe@1309: verification.comment = (verification.comment or "").. " /// Fiscal code matched" bsw/jbe@1309: else bsw/jbe@1309: slot.select("error", function() bsw/jbe@1309: ui.container{ content = _"Please check the fiscal code (invalid format or does not match name, first name and/or date of birth)" } bsw/jbe@1309: end) bsw/jbe@1309: errors = errors + 1 bsw/jbe@1309: --table.insert(manual_check_reasons, "fiscal code does not match (" .. fiscal_code_error .. ")") bsw/jbe@1309: end bsw/jbe@1309: end bsw/jbe@1309: bsw/jbe@1309: if errors > 0 then bsw/jbe@1309: return false bsw/jbe@1309: end bsw/jbe@1309: bsw/jbe@1309: local member = Member:new() bsw/jbe@1309: member.notify_email = email bsw/jbe@1309: member:save() bsw/jbe@1309: bsw/jbe@1309: for i, checkbox in ipairs(config.use_terms_checkboxes) do bsw/jbe@1309: local accepted = param.get("use_terms_checkbox_" .. checkbox.name, atom.boolean) bsw/jbe@1309: local member_useterms = MemberUseterms:new() bsw/jbe@1309: member_useterms.member_id = member.id bsw/jbe@1309: member_useterms.contract_identifier = checkbox.name bsw/jbe@1309: member_useterms:save() bsw/jbe@1309: end bsw/jbe@1309: bsw/jbe@1309: verification.requesting_member_id = member.id bsw/jbe@1309: bsw/jbe@1309: local manual_check_reasons = {} bsw/jbe@1309: bsw/jbe@1309: if manual_verification then bsw/jbe@1309: table.insert(manual_check_reasons, "User requested manual verification (during step 1)") bsw/jbe@1309: end bsw/jbe@1309: bsw@1316: if not config.self_registration.sms_id then bsw@1316: table.insert(manual_check_reasons, "User requested manual verification (during step 1)") bsw@1316: end bsw@1316: bsw/jbe@1309: local existing_verifications = Verification:new_selector() bsw/jbe@1309: :add_where{ "request_data->>'mobile_phone' = ?", mobile_phone } bsw/jbe@1309: :add_where("comment ilike '%SMS code%'") bsw/jbe@1309: :exec() bsw/jbe@1309: bsw/jbe@1309: if #existing_verifications > 0 then bsw/jbe@1309: table.insert(manual_check_reasons, "mobile phone number already used before") bsw/jbe@1309: end bsw/jbe@1309: bsw/jbe@1309: if #manual_check_reasons > 0 then bsw/jbe@1309: local reasons = table.concat(manual_check_reasons, ", ") bsw/jbe@1309: verification.comment = (verification.comment or "").. " /// Manual verification needed: " .. reasons bsw/jbe@1309: verification:save() bsw/jbe@1309: request.redirect{ external = encode.url { module = "registration", view = "register_manual_check_needed" } } bsw/jbe@1309: bsw/jbe@1309: else bsw/jbe@1309: local pin = multirand.string(6, "0123456789") bsw/jbe@1309: verification.request_data.sms_code = pin bsw/jbe@1309: verification.request_data.sms_code_tries = 3 bsw/jbe@1309: local sms_text = config.self_registration.sms_text bsw/jbe@1309: local sms_text = string.gsub(sms_text, "{PIN}", pin) bsw/jbe@1309: print("SMS Code: " .. sms_text) bsw/jbe@1309: local phone_number bsw/jbe@1309: if config.self_registration.sms_strip_leading_zero then bsw/jbe@1309: phone_number = string.match(verification.request_data.mobile_phone, "0(.+)") bsw/jbe@1309: else bsw/jbe@1309: phone_number = verification.request_data.mobile_phone bsw/jbe@1309: end bsw/jbe@1309: phone_number = config.self_registration.sms_prefix .. phone_number bsw/jbe@1309: local params = { bsw/jbe@1309: id = config.self_registration.sms_id, bsw/jbe@1309: pass = config.self_registration.sms_pass, bsw/jbe@1309: gateway = config.self_registration.sms_gateway, bsw/jbe@1309: absender = config.self_registration.sms_from, bsw/jbe@1309: text = sms_text, bsw/jbe@1309: nummer = phone_number, bsw/jbe@1309: test = config.self_registration.test and "1" or nil bsw/jbe@1309: } bsw/jbe@1309: local params_list = {} bsw/jbe@1309: for k, v in pairs(params) do bsw/jbe@1309: table.insert(params_list, encode.url_part(k) .. "=" .. encode.url_part(v)) bsw/jbe@1309: end bsw/jbe@1309: bsw/jbe@1309: local params_string = table.concat(params_list, "&") bsw/jbe@1309: local url = "http://gateway.any-sms.biz/send_sms.php?" .. params_string bsw/jbe@1309: print("curl " .. url) bsw/jbe@1309: local output, err, status = extos.pfilter(nil, "curl", url) bsw/jbe@1309: print(output) bsw/jbe@1309: verification.request_data.sms_code_sent_status = output bsw/jbe@1309: if not string.match(output, "^err:0") then bsw/jbe@1309: verification.comment = (verification.comment or "").. " /// Manual verification needed: sending SMS failed (" .. output .. ")" bsw/jbe@1309: verification:save() bsw/jbe@1309: request.redirect{ external = encode.url { module = "registration", view = "register_manual_check_needed" } } bsw/jbe@1309: return bsw/jbe@1309: end bsw/jbe@1309: verification.comment = (verification.comment or "") .. " /// SMS code " .. pin .. " sent" bsw/jbe@1309: verification:save() bsw/jbe@1309: request.redirect{ external = encode.url { module = "registration", view = "register_enter_pin", id = verification.id } } bsw/jbe@1309: end bsw/jbe@1309: bsw/jbe@1309: bsw/jbe@1309: