Docker image / push (push) Canceled after 0s
包含:登录失败锁定、90天密码有效期、30分钟会话超时、 强制改密、登录审计日志、屏幕水印、企业背景图、 备案信息固定底部、favicon、登录页JS修复等全部改动
238 lines
7.2 KiB
JavaScript
238 lines
7.2 KiB
JavaScript
import {forbidden, ok, serverError} from 'wix-http-functions';
|
|
import {authentication} from 'wix-members-backend';
|
|
import wixData from 'wix-data';
|
|
import {contacts} from 'wix-crm-backend';
|
|
import wixSecretsBackend from 'wix-secrets-backend';
|
|
|
|
|
|
// Validates that a request is valid, ie that the requesting server has used
|
|
// a valid API key, ie one that matches the one held in the Wix secrets manager.
|
|
// Parameters:
|
|
// request the request
|
|
// data the data in the request which must include
|
|
// key the API key
|
|
// secret_name the name of the secret in the Wix secrets manager that holds the API key
|
|
function validateRequest(request, data) {
|
|
|
|
return wixSecretsBackend.getSecret(data.secret_name)
|
|
.then((secret) => {
|
|
if (secret === data.key) {
|
|
return true;
|
|
}
|
|
else {
|
|
console.log("MRBS: invalid API key passed by IP address " + request.headers['x-real-ip']);
|
|
return false;
|
|
}
|
|
})
|
|
.catch((error) => {
|
|
console.error(error);
|
|
return false;
|
|
})
|
|
}
|
|
|
|
|
|
// The exported functions work by firing off two promises in parallel: the first
|
|
// validates that the request comes from an authorised server and the second does
|
|
// the actual work. When the two promises have been resolved or rejected, this
|
|
// function processes the promise results and issues the appropriate response.
|
|
function processPromiseResults(promiseResults) {
|
|
|
|
let result = {
|
|
"headers": {
|
|
"Content-Type": "application/json"
|
|
}
|
|
}
|
|
|
|
if ((promiseResults[0].status === 'rejected') || (promiseResults[1].status === 'rejected')) {
|
|
result.body = "internal server error";
|
|
return serverError(result);
|
|
}
|
|
else if (promiseResults[0].value === false) {
|
|
result.body = "forbidden";
|
|
return forbidden(result);
|
|
}
|
|
else {
|
|
result.body = promiseResults[1].value;
|
|
return ok(result);
|
|
}
|
|
}
|
|
|
|
|
|
// Validates a member's email login and password. Returns a boolean.
|
|
// Request data parameters:
|
|
// email the member's login email address
|
|
// password the password
|
|
export async function post_validateMember(request) {
|
|
|
|
const data = await request.body.json();
|
|
|
|
const validateRequestPromise = validateRequest(request, data);
|
|
|
|
const validateMemberPromise = authentication.login(data.email, data.password)
|
|
.then(() => {
|
|
return true;
|
|
})
|
|
.catch((error) => {
|
|
// If the email address and password are not valid then we will get
|
|
// an UNAUTHORIZED error. If it's any other kind then log it.
|
|
if (error.details.applicationError.code === "UNAUTHORIZED") {
|
|
console.error(error);
|
|
}
|
|
// Return false whatever the error
|
|
return false;
|
|
});
|
|
|
|
return Promise.allSettled([validateRequestPromise, validateMemberPromise])
|
|
.then((promiseResults) => {
|
|
return processPromiseResults(promiseResults);
|
|
})
|
|
}
|
|
|
|
|
|
// Gets a member's details given an email address. Returns a JSON object or NULL.
|
|
// Request data parameters:
|
|
// email the member's login email address
|
|
export async function post_getMemberByEmail(request) {
|
|
|
|
const data = await request.body.json();
|
|
|
|
const options = {
|
|
"suppressAuth": true,
|
|
"suppressHooks": true
|
|
};
|
|
|
|
const validateRequestPromise = validateRequest(request, data);
|
|
|
|
const getMemberPromise = wixData.query("Members/PrivateMembersData")
|
|
.eq("loginEmail", data.email)
|
|
.limit(1)
|
|
.find(options)
|
|
.then((members) => {
|
|
if(members.items.length > 0) {
|
|
let member = members.items[0];
|
|
// Now we've got the member we have to get (a) their full details (including
|
|
// custom fields, which aren't in PrivateMembersData) from Contacts using
|
|
// the id and (b) their badges from Members/Badges. Get these two sets of
|
|
// data in parallel using promises.
|
|
const getContactPromise = contacts.getContact(member._id, {suppressAuth: true})
|
|
.then((contact) => {
|
|
return {
|
|
member: member,
|
|
contact: contact
|
|
};
|
|
})
|
|
.catch((error) => {
|
|
console.error(error);
|
|
return null;
|
|
});
|
|
|
|
const getBadgesPromise = wixData.query("Members/Badges")
|
|
.find()
|
|
.then((results) => {
|
|
return results.items;
|
|
} );
|
|
|
|
return Promise.allSettled([getContactPromise, getBadgesPromise])
|
|
.then((promiseResults) => {
|
|
if ((promiseResults[0].status === 'fulfilled') && (promiseResults[1].status ==='fulfilled')) {
|
|
let result = promiseResults[0].value;
|
|
result.badges = [];
|
|
// Iterate through the badges checking if this member has the badge
|
|
if (promiseResults[1].value) {
|
|
promiseResults[1].value.forEach(badge => {
|
|
if (badge.members.includes(member._id)) {
|
|
result.badges.push(badge.title);
|
|
}
|
|
});
|
|
}
|
|
return result;
|
|
}
|
|
else {
|
|
return null;
|
|
}
|
|
})
|
|
}
|
|
else {
|
|
return null;
|
|
}
|
|
})
|
|
.catch((error) => {
|
|
console.error(error);
|
|
return null;
|
|
});
|
|
|
|
return Promise.allSettled([validateRequestPromise, getMemberPromise])
|
|
.then((promiseResults) => {
|
|
return processPromiseResults(promiseResults);
|
|
})
|
|
}
|
|
|
|
|
|
// Returns an array of members indexed by 'username' and 'display_name'
|
|
// Request data parameters:
|
|
// limit (optional) the limit to be used in each query. Defaults to 50.
|
|
// display_name_property (optional) the member property to be used for the display name.
|
|
// Typically either 'name' (the default) or 'nickname'.
|
|
export async function post_getMemberNames(request) {
|
|
|
|
const data = await request.body.json();
|
|
|
|
const displayNameProperty = data.display_name_property ?? 'name';
|
|
|
|
const options = {
|
|
"suppressAuth": true,
|
|
"suppressHooks": true
|
|
};
|
|
|
|
const defaultLimit = 50;
|
|
let memberNames = [];
|
|
let limit = defaultLimit;
|
|
|
|
if (data.limit !== undefined) {
|
|
limit = parseInt(data.limit, 10);
|
|
if (isNaN(limit) || (limit <= 0)) {
|
|
limit =defaultLimit;
|
|
}
|
|
}
|
|
|
|
function extractMemberNames(items) {
|
|
|
|
let result = [];
|
|
|
|
items.forEach(function(item) {
|
|
result.push({
|
|
username: item.loginEmail,
|
|
display_name: ((item[displayNameProperty] === undefined) ||
|
|
(item[displayNameProperty] === null) ||
|
|
(item[displayNameProperty] === '')) ? item.loginEmail : item[displayNameProperty]
|
|
});
|
|
});
|
|
|
|
return result;
|
|
}
|
|
|
|
const validateRequestPromise = validateRequest(request, data);
|
|
|
|
const getMemberNamesPromise = wixData.query("Members/PrivateMembersData")
|
|
.limit(limit)
|
|
.find(options)
|
|
.then(async (results) => {
|
|
memberNames = memberNames.concat(extractMemberNames(results.items));
|
|
while (results.hasNext()) {
|
|
results = await results.next();
|
|
memberNames = memberNames.concat(extractMemberNames(results.items));
|
|
}
|
|
})
|
|
.catch((error) => {
|
|
console.error(error);
|
|
})
|
|
.then(() => {
|
|
return memberNames;
|
|
})
|
|
|
|
return Promise.allSettled([validateRequestPromise, getMemberNamesPromise])
|
|
.then((promiseResults) => {
|
|
return processPromiseResults(promiseResults);
|
|
})
|
|
}
|