fix(client/api): ms trophy validation (#51892)
parent
89f0310372
commit
9b50d54001
|
@ -719,14 +719,42 @@ function createMsTrophyChallengeCompleted(app) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const { msTrophyId = '' } = challenge;
|
const { msTrophyId = '' } = challenge;
|
||||||
const msTrophyApiUrl = `https://learn.microsoft.com/api/gamestatus/achievements/${msTrophyId}?username=${msUsername}&locale=en-us`;
|
|
||||||
const msApiRes = await fetch(msTrophyApiUrl);
|
|
||||||
const msTrophyJson = await msApiRes.json();
|
|
||||||
|
|
||||||
if (!msApiRes.ok || msTrophyJson.awardType !== 'Trophy') {
|
const msProfileApi = `https://learn.microsoft.com/api/profiles/${msUsername}`;
|
||||||
|
const msProfileApiRes = await fetch(msProfileApi);
|
||||||
|
const msProfileJson = await msProfileApiRes.json();
|
||||||
|
|
||||||
|
if (!msProfileApiRes.ok || !msProfileJson.userId) {
|
||||||
return res.status(403).json({
|
return res.status(403).json({
|
||||||
type: 'error',
|
type: 'error',
|
||||||
message: 'flash.ms.trophy.err-3',
|
message: 'flash.ms.profile.err',
|
||||||
|
variables: {
|
||||||
|
msUsername
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const { userId } = msProfileJson;
|
||||||
|
|
||||||
|
const msGameStatusApi = `https://learn.microsoft.com/api/gamestatus/${userId}`;
|
||||||
|
const msGameStatusApiRes = await fetch(msGameStatusApi);
|
||||||
|
const msGameStatusJson = await msGameStatusApiRes.json();
|
||||||
|
|
||||||
|
if (!msGameStatusApiRes.ok) {
|
||||||
|
return res.status(403).json({
|
||||||
|
type: 'error',
|
||||||
|
message: 'flash.ms.trophy.err-3'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const hasEarnedTrophy = msGameStatusJson.achievements?.some(
|
||||||
|
a => a.awardUid === msTrophyId
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!hasEarnedTrophy) {
|
||||||
|
return res.status(403).json({
|
||||||
|
type: 'error',
|
||||||
|
message: 'flash.ms.trophy.err-4',
|
||||||
variables: {
|
variables: {
|
||||||
msUsername
|
msUsername
|
||||||
}
|
}
|
||||||
|
@ -735,7 +763,7 @@ function createMsTrophyChallengeCompleted(app) {
|
||||||
|
|
||||||
const completedChallenge = pick(body, ['id']);
|
const completedChallenge = pick(body, ['id']);
|
||||||
|
|
||||||
completedChallenge.solution = msTrophyApiUrl;
|
completedChallenge.solution = msGameStatusApi;
|
||||||
completedChallenge.completedDate = Date.now();
|
completedChallenge.completedDate = Date.now();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -765,7 +793,7 @@ function createMsTrophyChallengeCompleted(app) {
|
||||||
log(e);
|
log(e);
|
||||||
return res.status(500).json({
|
return res.status(500).json({
|
||||||
type: 'error',
|
type: 'error',
|
||||||
message: 'flash.ms.trophy.err-4'
|
message: 'flash.ms.trophy.err-5'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -732,11 +732,15 @@
|
||||||
"unlinked": "The link to your Microsoft username has been removed.",
|
"unlinked": "The link to your Microsoft username has been removed.",
|
||||||
"unlink-err": "Something went wrong trying to remove the link to your Microsoft username."
|
"unlink-err": "Something went wrong trying to remove the link to your Microsoft username."
|
||||||
},
|
},
|
||||||
|
"profile": {
|
||||||
|
"err": "We could not find a Microsoft user ID for Microsoft user \"{{msUsername}}\""
|
||||||
|
},
|
||||||
"trophy": {
|
"trophy": {
|
||||||
"err-1": "We could not find a Microsoft username associated with your freeCodeCamp account.",
|
"err-1": "We could not find a Microsoft username associated with your freeCodeCamp account.",
|
||||||
"err-2": "You are trying to submit a challenge that does not appear to be a trophy challenge.",
|
"err-2": "You are trying to submit a challenge that does not appear to be a trophy challenge.",
|
||||||
"err-3": "It appears that the Microsoft user \"{{msUsername}}\" has not earned this trophy.",
|
"err-3": "We could not get your Microsoft profile from your Microsoft ID.",
|
||||||
"err-4": "Something went wrong trying to verify your trophy. Please check and try again.",
|
"err-4": "It appears that the Microsoft user \"{{msUsername}}\" has not earned this trophy.",
|
||||||
|
"err-5": "Something went wrong trying to verify your trophy. Please check and try again.",
|
||||||
"verified": "Your trophy from Microsoft's learning platform was verified."
|
"verified": "Your trophy from Microsoft's learning platform was verified."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -16,7 +16,8 @@ function Flash({ flashMessage, removeFlashMessage }: FlashProps): JSX.Element {
|
||||||
const { type, message, id, variables } = flashMessage;
|
const { type, message, id, variables } = flashMessage;
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const flashStyle = type as AlertProps['variant'];
|
const flashStyle =
|
||||||
|
type === 'error' ? 'danger' : (type as AlertProps['variant']);
|
||||||
|
|
||||||
function handleClose() {
|
function handleClose() {
|
||||||
removeFlashMessage();
|
removeFlashMessage();
|
||||||
|
|
|
@ -27,10 +27,12 @@ export enum FlashMessages {
|
||||||
MsTranscriptLinked = 'flash.ms.transcript.linked',
|
MsTranscriptLinked = 'flash.ms.transcript.linked',
|
||||||
MsTranscriptUnlinked = 'flash.ms.transcript.unlinked',
|
MsTranscriptUnlinked = 'flash.ms.transcript.unlinked',
|
||||||
MsTranscriptUnlinkErr = 'flash.ms.transcript.unlink-err',
|
MsTranscriptUnlinkErr = 'flash.ms.transcript.unlink-err',
|
||||||
|
MsProfileErr = 'flash.ms.profile.err',
|
||||||
MsTrophyErr1 = 'flash.ms.trophy.err-1',
|
MsTrophyErr1 = 'flash.ms.trophy.err-1',
|
||||||
MsTrophyErr2 = 'flash.ms.trophy.err-2',
|
MsTrophyErr2 = 'flash.ms.trophy.err-2',
|
||||||
MsTrophyErr3 = 'flash.ms.trophy.err-3',
|
MsTrophyErr3 = 'flash.ms.trophy.err-3',
|
||||||
MsTrophyErr4 = 'flash.ms.trophy.err-4',
|
MsTrophyErr4 = 'flash.ms.trophy.err-4',
|
||||||
|
MsTrophyErr5 = 'flash.ms.trophy.err-5',
|
||||||
MsTrophyVerified = 'flash.ms.trophy.verified',
|
MsTrophyVerified = 'flash.ms.trophy.verified',
|
||||||
NameNeeded = 'flash.name-needed',
|
NameNeeded = 'flash.name-needed',
|
||||||
None = '',
|
None = '',
|
||||||
|
|
|
@ -42,10 +42,12 @@ const toneUrls = {
|
||||||
[FlashMessages.MsTranscriptLinked]: CHAL_COMP,
|
[FlashMessages.MsTranscriptLinked]: CHAL_COMP,
|
||||||
[FlashMessages.MsTranscriptUnlinked]: CHAL_COMP,
|
[FlashMessages.MsTranscriptUnlinked]: CHAL_COMP,
|
||||||
[FlashMessages.MsTranscriptUnlinkErr]: TRY_AGAIN,
|
[FlashMessages.MsTranscriptUnlinkErr]: TRY_AGAIN,
|
||||||
|
[FlashMessages.MsProfileErr]: TRY_AGAIN,
|
||||||
[FlashMessages.MsTrophyErr1]: TRY_AGAIN,
|
[FlashMessages.MsTrophyErr1]: TRY_AGAIN,
|
||||||
[FlashMessages.MsTrophyErr2]: TRY_AGAIN,
|
[FlashMessages.MsTrophyErr2]: TRY_AGAIN,
|
||||||
[FlashMessages.MsTrophyErr3]: TRY_AGAIN,
|
[FlashMessages.MsTrophyErr3]: TRY_AGAIN,
|
||||||
[FlashMessages.MsTrophyErr4]: TRY_AGAIN,
|
[FlashMessages.MsTrophyErr4]: TRY_AGAIN,
|
||||||
|
[FlashMessages.MsTrophyErr5]: TRY_AGAIN,
|
||||||
[FlashMessages.MsTrophyVerified]: CHAL_COMP,
|
[FlashMessages.MsTrophyVerified]: CHAL_COMP,
|
||||||
[FlashMessages.NameNeeded]: TRY_AGAIN,
|
[FlashMessages.NameNeeded]: TRY_AGAIN,
|
||||||
// [FlashMessages.None]: '',
|
// [FlashMessages.None]: '',
|
||||||
|
|
Loading…
Reference in New Issue