@casual-simulation/aux-records
Advanced tools
Comparing version 3.1.14-alpha.3661157217 to 3.1.23-alpha.4227183169
@@ -1,4 +0,5 @@ | ||
import { AddressType, AuthStore } from './AuthStore'; | ||
import { AddressType, AuthStore, AuthUser } from './AuthStore'; | ||
import { ServerError } from './Errors'; | ||
import { AuthMessenger } from './AuthMessenger'; | ||
import { RegexRule } from './Utils'; | ||
/** | ||
@@ -62,2 +63,20 @@ * The number of miliseconds that a login request should be valid for before expiration. | ||
listSessions(request: ListSessionsRequest): Promise<ListSessionsResult>; | ||
/** | ||
* Gets the information for a specific user. | ||
* @param request The request. | ||
*/ | ||
getUserInfo(request: GetUserInfoRequest): Promise<GetUserInfoResult>; | ||
/** | ||
* Attempts to update a user's metadata. | ||
* @param request The request for the operation. | ||
*/ | ||
updateUserInfo(request: UpdateUserInfoRequest): Promise<UpdateUserInfoResult>; | ||
/** | ||
* Lists the email rules that should be used. | ||
*/ | ||
listEmailRules(): Promise<ListEmailRulesResult>; | ||
/** | ||
* Lists the SMS rules that should be used. | ||
*/ | ||
listSmsRules(): Promise<ListSmsRulesResult>; | ||
} | ||
@@ -230,3 +249,3 @@ export interface LoginRequest { | ||
/** | ||
* | ||
*The list of sessions. | ||
*/ | ||
@@ -308,2 +327,98 @@ sessions: ListedSession[]; | ||
} | ||
/** | ||
* Defines an interface for requests to get a user's info. | ||
*/ | ||
export interface GetUserInfoRequest { | ||
/** | ||
* The session key that should be used to authenticate the request. | ||
*/ | ||
sessionKey: string; | ||
/** | ||
* The ID of the user whose info should be retrieved. | ||
*/ | ||
userId: string; | ||
} | ||
export declare type GetUserInfoResult = GetUserInfoSuccess | GetUserInfoFailure; | ||
export interface GetUserInfoSuccess { | ||
success: true; | ||
/** | ||
* The ID of the user that was retrieved. | ||
*/ | ||
userId: string; | ||
/** | ||
* The name of the user. | ||
*/ | ||
name: string; | ||
/** | ||
* The URL of the avatar for the user. | ||
*/ | ||
avatarUrl: string; | ||
/** | ||
* The URL of the avatar portrait for the user. | ||
*/ | ||
avatarPortraitUrl: string; | ||
/** | ||
* The email address of the user. | ||
*/ | ||
email: string; | ||
/** | ||
* The phone number of the user. | ||
*/ | ||
phoneNumber: string; | ||
} | ||
export interface GetUserInfoFailure { | ||
success: false; | ||
errorCode: 'unacceptable_user_id' | ValidateSessionKeyFailure['errorCode'] | ServerError; | ||
errorMessage: string; | ||
} | ||
/** | ||
* Defines an interface for a request to update user info. | ||
*/ | ||
export interface UpdateUserInfoRequest { | ||
/** | ||
* The session key that should be used to authenticate the request. | ||
*/ | ||
sessionKey: string; | ||
/** | ||
* The ID of the user whose info should be updated. | ||
*/ | ||
userId: string; | ||
/** | ||
* The new info for the user. | ||
*/ | ||
update: Partial<Pick<AuthUser, 'name' | 'email' | 'phoneNumber' | 'avatarUrl' | 'avatarPortraitUrl'>>; | ||
} | ||
export declare type UpdateUserInfoResult = UpdateUserInfoSuccess | UpdateUserInfoFailure; | ||
export interface UpdateUserInfoSuccess { | ||
success: true; | ||
/** | ||
* The ID of the user that was retrieved. | ||
*/ | ||
userId: string; | ||
} | ||
export interface UpdateUserInfoFailure { | ||
success: false; | ||
errorCode: 'unacceptable_user_id' | 'unacceptable_update' | ValidateSessionKeyFailure['errorCode'] | ServerError; | ||
errorMessage: string; | ||
} | ||
export declare type ListEmailRulesResult = ListEmailRulesSuccess | ListEmailRulesFailure; | ||
export interface ListEmailRulesSuccess { | ||
success: true; | ||
rules: RegexRule[]; | ||
} | ||
export interface ListEmailRulesFailure { | ||
success: false; | ||
errorCode: ServerError; | ||
errorMessage: string; | ||
} | ||
export declare type ListSmsRulesResult = ListSmsRulesSuccess | ListSmsRulesFailure; | ||
export interface ListSmsRulesSuccess { | ||
success: true; | ||
rules: RegexRule[]; | ||
} | ||
export interface ListSmsRulesFailure { | ||
success: false; | ||
errorCode: ServerError; | ||
errorMessage: string; | ||
} | ||
//# sourceMappingURL=AuthController.d.ts.map |
@@ -12,4 +12,5 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
import { randomBytes } from 'tweetnacl'; | ||
import { hashPasswordWithSalt, verifyPasswordAgainstHashes, } from '@casual-simulation/crypto'; | ||
import { hashHighEntropyPasswordWithSalt, hashPasswordWithSalt, verifyPasswordAgainstHashes, } from '@casual-simulation/crypto'; | ||
import { fromByteArray } from 'base64-js'; | ||
import { cleanupObject, } from './Utils'; | ||
import { formatV1SessionKey, parseSessionKey, randomCode } from './AuthUtils'; | ||
@@ -271,3 +272,5 @@ /** | ||
requestId: loginRequest.requestId, | ||
secretHash: hashPasswordWithSalt(sessionSecret, sessionId), | ||
// sessionSecret and sessionId are high-entropy (128 bits of random data) | ||
// so we should use a hash that is optimized for high-entropy inputs. | ||
secretHash: hashHighEntropyPasswordWithSalt(sessionSecret, sessionId), | ||
grantedTimeMs: now, | ||
@@ -653,3 +656,173 @@ revokeTimeMs: null, | ||
} | ||
/** | ||
* Gets the information for a specific user. | ||
* @param request The request. | ||
*/ | ||
getUserInfo(request) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (typeof request.userId !== 'string' || request.userId === '') { | ||
return { | ||
success: false, | ||
errorCode: 'unacceptable_user_id', | ||
errorMessage: 'The given userId is invalid. It must be a string.', | ||
}; | ||
} | ||
else if (typeof request.sessionKey !== 'string' || | ||
request.sessionKey === '') { | ||
return { | ||
success: false, | ||
errorCode: 'unacceptable_session_key', | ||
errorMessage: 'The given session key is invalid. It must be a string.', | ||
}; | ||
} | ||
try { | ||
const keyResult = yield this.validateSessionKey(request.sessionKey); | ||
if (keyResult.success === false) { | ||
return keyResult; | ||
} | ||
else if (keyResult.userId !== request.userId) { | ||
return { | ||
success: false, | ||
errorCode: 'invalid_key', | ||
errorMessage: INVALID_KEY_ERROR_MESSAGE, | ||
}; | ||
} | ||
const result = yield this._store.findUser(request.userId); | ||
if (!result) { | ||
throw new Error('Unable to find user even though a valid session key was presented!'); | ||
} | ||
return { | ||
success: true, | ||
userId: result.id, | ||
name: result.name, | ||
email: result.email, | ||
phoneNumber: result.phoneNumber, | ||
avatarPortraitUrl: result.avatarPortraitUrl, | ||
avatarUrl: result.avatarUrl, | ||
}; | ||
} | ||
catch (err) { | ||
console.error('[AuthController] Error ocurred while getting user info', err); | ||
return { | ||
success: false, | ||
errorCode: 'server_error', | ||
errorMessage: 'A server error occurred.', | ||
}; | ||
} | ||
}); | ||
} | ||
/** | ||
* Attempts to update a user's metadata. | ||
* @param request The request for the operation. | ||
*/ | ||
updateUserInfo(request) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (typeof request.userId !== 'string' || request.userId === '') { | ||
return { | ||
success: false, | ||
errorCode: 'unacceptable_user_id', | ||
errorMessage: 'The given userId is invalid. It must be a string.', | ||
}; | ||
} | ||
else if (typeof request.sessionKey !== 'string' || | ||
request.sessionKey === '') { | ||
return { | ||
success: false, | ||
errorCode: 'unacceptable_session_key', | ||
errorMessage: 'The given session key is invalid. It must be a string.', | ||
}; | ||
} | ||
else if (typeof request.update !== 'object' || | ||
request.update === null || | ||
Array.isArray(request.update)) { | ||
return { | ||
success: false, | ||
errorCode: 'unacceptable_update', | ||
errorMessage: 'The given update is invalid. It must be an object.', | ||
}; | ||
} | ||
try { | ||
const keyResult = yield this.validateSessionKey(request.sessionKey); | ||
if (keyResult.success === false) { | ||
return keyResult; | ||
} | ||
else if (keyResult.userId !== request.userId) { | ||
return { | ||
success: false, | ||
errorCode: 'invalid_key', | ||
errorMessage: INVALID_KEY_ERROR_MESSAGE, | ||
}; | ||
} | ||
const user = yield this._store.findUser(request.userId); | ||
if (!user) { | ||
throw new Error('Unable to find user even though a valid session key was presented!'); | ||
} | ||
const cleaned = cleanupObject({ | ||
name: request.update.name, | ||
avatarUrl: request.update.avatarUrl, | ||
avatarPortraitUrl: request.update.avatarPortraitUrl, | ||
email: request.update.email, | ||
phoneNumber: request.update.phoneNumber, | ||
}); | ||
yield this._store.saveUser(Object.assign(Object.assign({}, user), cleaned)); | ||
return { | ||
success: true, | ||
userId: user.id, | ||
}; | ||
} | ||
catch (err) { | ||
console.error('[AuthController] Error ocurred while getting user info', err); | ||
return { | ||
success: false, | ||
errorCode: 'server_error', | ||
errorMessage: 'A server error occurred.', | ||
}; | ||
} | ||
}); | ||
} | ||
/** | ||
* Lists the email rules that should be used. | ||
*/ | ||
listEmailRules() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
try { | ||
const rules = yield this._store.listEmailRules(); | ||
return { | ||
success: true, | ||
rules, | ||
}; | ||
} | ||
catch (err) { | ||
console.error('[AuthController] Error ocurred while listing email rules', err); | ||
return { | ||
success: false, | ||
errorCode: 'server_error', | ||
errorMessage: 'A server error occurred.', | ||
}; | ||
} | ||
}); | ||
} | ||
/** | ||
* Lists the SMS rules that should be used. | ||
*/ | ||
listSmsRules() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
try { | ||
const rules = yield this._store.listSmsRules(); | ||
return { | ||
success: true, | ||
rules, | ||
}; | ||
} | ||
catch (err) { | ||
console.error('[AuthController] Error ocurred while listing email rules', err); | ||
return { | ||
success: false, | ||
errorCode: 'server_error', | ||
errorMessage: 'A server error occurred.', | ||
}; | ||
} | ||
}); | ||
} | ||
} | ||
//# sourceMappingURL=AuthController.js.map |
@@ -0,1 +1,2 @@ | ||
import { RegexRule } from 'Utils'; | ||
import { ServerError } from './Errors'; | ||
@@ -82,2 +83,10 @@ /** | ||
setCurrentLoginRequest(userId: string, requestId: string): Promise<void>; | ||
/** | ||
* Gets the list of email rules. | ||
*/ | ||
listEmailRules(): Promise<RegexRule[]>; | ||
/** | ||
* Gets the list of SMS rules. | ||
*/ | ||
listSmsRules(): Promise<RegexRule[]>; | ||
} | ||
@@ -84,0 +93,0 @@ export declare type AddressType = 'email' | 'phone'; |
@@ -1,2 +0,2 @@ | ||
import { FileRecordsStore, AddFileFailure, MarkFileRecordAsUploadedFailure, EraseFileStoreResult } from './FileRecordsStore'; | ||
import { FileRecordsStore, AddFileFailure, MarkFileRecordAsUploadedFailure, EraseFileStoreResult, GetFileNameFromUrlResult } from './FileRecordsStore'; | ||
import { NotLoggedInError, ServerError } from './Errors'; | ||
@@ -20,2 +20,4 @@ import { RecordsController, ValidatePublicRecordKeyFailure } from './RecordsController'; | ||
markFileAsUploaded(recordName: string, fileName: string): Promise<FileUploadedResult>; | ||
getFileNameFromUrl(fileUrl: string): Promise<GetFileNameFromUrlResult>; | ||
getAllowedUploadHeaders(): string[]; | ||
} | ||
@@ -22,0 +24,0 @@ /** |
@@ -96,6 +96,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
catch (err) { | ||
console.error('[FileRecordsController] An error occurred while recording a file:', err); | ||
return { | ||
success: false, | ||
errorCode: 'server_error', | ||
errorMessage: err.toString(), | ||
errorMessage: 'A server error occurred.', | ||
}; | ||
@@ -142,6 +143,7 @@ } | ||
catch (err) { | ||
console.error('[FileRecordsController] An error occurred while erasing a file:', err); | ||
return { | ||
success: false, | ||
errorCode: 'server_error', | ||
errorMessage: err.toString(), | ||
errorMessage: 'A server error occurred.', | ||
}; | ||
@@ -163,6 +165,7 @@ } | ||
catch (err) { | ||
console.error('[FileRecordsController] An error occurred while marking a file as uploaded:', err); | ||
return { | ||
success: false, | ||
errorCode: 'server_error', | ||
errorMessage: err.toString(), | ||
errorMessage: 'A server error occurred.', | ||
}; | ||
@@ -172,3 +175,21 @@ } | ||
} | ||
getFileNameFromUrl(fileUrl) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
try { | ||
return yield this._store.getFileNameFromUrl(fileUrl); | ||
} | ||
catch (err) { | ||
console.error('[FileRecordsController] An error occurred while getting a file name:', err); | ||
return { | ||
success: false, | ||
errorCode: 'server_error', | ||
errorMessage: 'A server error occurred.', | ||
}; | ||
} | ||
}); | ||
} | ||
getAllowedUploadHeaders() { | ||
return this._store.getAllowedUploadHeaders(); | ||
} | ||
} | ||
//# sourceMappingURL=FileRecordsController.js.map |
@@ -40,2 +40,11 @@ import { ServerError } from './Errors'; | ||
eraseFileRecord(recordName: string, fileName: string): Promise<EraseFileStoreResult>; | ||
/** | ||
* Attempts to get the record name and file name from the given URL. | ||
* @param fileUrl The URL. | ||
*/ | ||
getFileNameFromUrl(fileUrl: string): Promise<GetFileNameFromUrlResult>; | ||
/** | ||
* Gets the list of headers that should be allowed via CORS. | ||
*/ | ||
getAllowedUploadHeaders(): string[]; | ||
} | ||
@@ -158,2 +167,20 @@ export declare type GetFileRecordResult = GetFileRecordSuccess | GetFileRecordFailure; | ||
} | ||
export declare type GetFileNameFromUrlResult = GetFileNameFromUrlSuccess | GetFileNameFromUrlFailure; | ||
export interface GetFileNameFromUrlSuccess { | ||
success: true; | ||
/** | ||
* The name of the record that the URL references. | ||
* Null if the URL contains no record name. | ||
*/ | ||
recordName: string | null; | ||
/** | ||
* The name of the file that the URL references. | ||
*/ | ||
fileName: string; | ||
} | ||
export interface GetFileNameFromUrlFailure { | ||
success: false; | ||
errorCode: ServerError | 'unacceptable_url'; | ||
errorMessage: string; | ||
} | ||
//# sourceMappingURL=FileRecordsStore.d.ts.map |
@@ -14,2 +14,3 @@ export * from './RecordsController'; | ||
export * from './LivekitEvents'; | ||
export * from './RecordsHttpServer'; | ||
//# sourceMappingURL=index.d.ts.map |
@@ -14,2 +14,3 @@ export * from './RecordsController'; | ||
export * from './LivekitEvents'; | ||
export * from './RecordsHttpServer'; | ||
//# sourceMappingURL=index.js.map |
@@ -0,1 +1,2 @@ | ||
import { RegexRule } from './Utils'; | ||
import { AddressType, AuthLoginRequest, AuthSession, AuthStore, AuthUser, ListSessionsDataResult, SaveNewUserResult } from './AuthStore'; | ||
@@ -6,5 +7,9 @@ export declare class MemoryAuthStore implements AuthStore { | ||
private _sessions; | ||
private _emailRules; | ||
private _smsRules; | ||
get users(): AuthUser[]; | ||
get loginRequests(): AuthLoginRequest[]; | ||
get sessions(): AuthSession[]; | ||
get emailRules(): RegexRule[]; | ||
get smsRules(): RegexRule[]; | ||
saveUser(user: AuthUser): Promise<void>; | ||
@@ -23,4 +28,6 @@ saveNewUser(user: AuthUser): Promise<SaveNewUserResult>; | ||
listSessions(userId: string, expireTimeMs: number): Promise<ListSessionsDataResult>; | ||
listEmailRules(): Promise<RegexRule[]>; | ||
listSmsRules(): Promise<RegexRule[]>; | ||
private _findUserIndex; | ||
} | ||
//# sourceMappingURL=MemoryAuthStore.d.ts.map |
@@ -16,2 +16,4 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
this._sessions = []; | ||
this._emailRules = []; | ||
this._smsRules = []; | ||
} | ||
@@ -27,2 +29,8 @@ get users() { | ||
} | ||
get emailRules() { | ||
return this._emailRules; | ||
} | ||
get smsRules() { | ||
return this._smsRules; | ||
} | ||
saveUser(user) { | ||
@@ -154,2 +162,12 @@ return __awaiter(this, void 0, void 0, function* () { | ||
} | ||
listEmailRules() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
return this._emailRules.slice(); | ||
}); | ||
} | ||
listSmsRules() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
return this._smsRules.slice(); | ||
}); | ||
} | ||
_findUserIndex(id) { | ||
@@ -156,0 +174,0 @@ return this._users.findIndex((u) => u.id === id); |
@@ -1,5 +0,7 @@ | ||
import { AddFileResult, EraseFileStoreResult, FileRecordsStore, GetFileRecordResult, MarkFileRecordAsUploadedResult, PresignFileUploadRequest, PresignFileUploadResult } from './FileRecordsStore'; | ||
import { AddFileResult, EraseFileStoreResult, FileRecordsStore, GetFileNameFromUrlResult, GetFileRecordResult, MarkFileRecordAsUploadedResult, PresignFileUploadRequest, PresignFileUploadResult } from './FileRecordsStore'; | ||
export declare class MemoryFileRecordsStore implements FileRecordsStore { | ||
private _files; | ||
private _fileUploadUrl; | ||
presignFileUpload(request: PresignFileUploadRequest): Promise<PresignFileUploadResult>; | ||
getFileNameFromUrl(fileUrl: string): Promise<GetFileNameFromUrlResult>; | ||
getFileRecord(recordName: string, fileName: string): Promise<GetFileRecordResult>; | ||
@@ -9,3 +11,4 @@ addFileRecord(recordName: string, fileName: string, publisherId: string, subjectId: string, sizeInBytes: number, description: string): Promise<AddFileResult>; | ||
eraseFileRecord(recordName: string, fileName: string): Promise<EraseFileStoreResult>; | ||
getAllowedUploadHeaders(): string[]; | ||
} | ||
//# sourceMappingURL=MemoryFileRecordsStore.d.ts.map |
@@ -13,6 +13,48 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
this._files = new Map(); | ||
this._fileUploadUrl = 'http://localhost:9191'; | ||
} | ||
presignFileUpload(request) { | ||
throw new Error('Method not implemented.'); | ||
return __awaiter(this, void 0, void 0, function* () { | ||
return { | ||
success: true, | ||
uploadHeaders: Object.assign(Object.assign({}, request.headers), { 'record-name': request.recordName, 'content-type': request.fileMimeType }), | ||
uploadMethod: 'POST', | ||
uploadUrl: `${this._fileUploadUrl}/${request.recordName}/${request.fileName}`, | ||
}; | ||
}); | ||
} | ||
getFileNameFromUrl(fileUrl) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (fileUrl.startsWith(this._fileUploadUrl)) { | ||
let recordNameAndFileName = fileUrl.slice(this._fileUploadUrl.length + 1); | ||
let nextSlash = recordNameAndFileName.indexOf('/'); | ||
if (nextSlash < 0) { | ||
return { | ||
success: false, | ||
errorCode: 'unacceptable_url', | ||
errorMessage: 'The URL does not match an expected format.', | ||
}; | ||
} | ||
let recordName = recordNameAndFileName.slice(0, nextSlash); | ||
let fileName = recordNameAndFileName.slice(nextSlash + 1); | ||
if (recordName && fileName) { | ||
return { | ||
success: true, | ||
recordName, | ||
fileName, | ||
}; | ||
} | ||
return { | ||
success: false, | ||
errorCode: 'unacceptable_url', | ||
errorMessage: 'The URL does not match an expected format.', | ||
}; | ||
} | ||
return { | ||
success: false, | ||
errorCode: 'unacceptable_url', | ||
errorMessage: 'The URL does not match an expected format.', | ||
}; | ||
}); | ||
} | ||
getFileRecord(recordName, fileName) { | ||
@@ -98,3 +140,6 @@ return __awaiter(this, void 0, void 0, function* () { | ||
} | ||
getAllowedUploadHeaders() { | ||
return ['record-name', 'content-type']; | ||
} | ||
} | ||
//# sourceMappingURL=MemoryFileRecordsStore.js.map |
{ | ||
"name": "@casual-simulation/aux-records", | ||
"version": "3.1.14-alpha.3661157217", | ||
"version": "3.1.23-alpha.4227183169", | ||
"description": "Helpers and managers used by the CasualOS records system.", | ||
@@ -40,7 +40,7 @@ "keywords": [], | ||
"dependencies": { | ||
"@casual-simulation/crypto": "^3.1.14-alpha.3661157217", | ||
"@casual-simulation/crypto": "^3.1.23-alpha.4227183169", | ||
"livekit-server-sdk": "1.0.2", | ||
"tweetnacl": "1.0.3" | ||
}, | ||
"gitHead": "1a4688a5c80f36121fd0458346f944ea81fec2dd" | ||
"gitHead": "b5a541f95bcfb41de2e2c2a04a5cff19d70ec09f" | ||
} |
@@ -11,3 +11,3 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
import { toBase64String, fromBase64String } from './Utils'; | ||
import { hashPasswordWithSalt, } from '@casual-simulation/crypto'; | ||
import { hashHighEntropyPasswordWithSalt, hashPasswordWithSalt, } from '@casual-simulation/crypto'; | ||
import { randomBytes } from 'tweetnacl'; | ||
@@ -63,3 +63,3 @@ import { fromByteArray } from 'base64-js'; | ||
const salt = record.secretSalt; | ||
const passwordHash = hashPasswordWithSalt(password, salt); | ||
const passwordHash = hashHighEntropyPasswordWithSalt(password, salt); | ||
yield this._store.addRecordKey({ | ||
@@ -81,3 +81,3 @@ recordName: name, | ||
const salt = fromByteArray(randomBytes(16)); | ||
const passwordHash = hashPasswordWithSalt(password, salt); | ||
const passwordHash = hashHighEntropyPasswordWithSalt(password, salt); | ||
yield this._store.addRecord({ | ||
@@ -138,10 +138,11 @@ name, | ||
} | ||
const hash = hashPasswordWithSalt(password, record.secretSalt); | ||
// Check v2 hashes first because they are much quicker to check | ||
const hashV2 = hashHighEntropyPasswordWithSalt(password, record.secretSalt); | ||
let valid = false; | ||
let resultPolicy = DEFAULT_RECORD_KEY_POLICY; | ||
if (record.secretHashes.some((h) => h === hash)) { | ||
if (record.secretHashes.some((h) => h === hashV2)) { | ||
valid = true; | ||
} | ||
else { | ||
const key = yield this._store.getRecordKeyByRecordAndHash(name, hash); | ||
const key = yield this._store.getRecordKeyByRecordAndHash(name, hashV2); | ||
if (!!key) { | ||
@@ -151,2 +152,16 @@ resultPolicy = key.policy; | ||
} | ||
else { | ||
// Check v1 hashes | ||
const hash = hashPasswordWithSalt(password, record.secretSalt); | ||
if (record.secretHashes.some((h) => h === hash)) { | ||
valid = true; | ||
} | ||
else { | ||
const key = yield this._store.getRecordKeyByRecordAndHash(name, hash); | ||
if (!!key) { | ||
resultPolicy = key.policy; | ||
valid = true; | ||
} | ||
} | ||
} | ||
} | ||
@@ -153,0 +168,0 @@ if (resultPolicy !== policy) { |
@@ -79,2 +79,31 @@ /** | ||
}): 401 | 501 | 404 | 400 | 200 | 403 | 500; | ||
/** | ||
* Clones the given object into a new object that only has non-null and not-undefined properties. | ||
* @param obj The object to cleanup. | ||
*/ | ||
export declare function cleanupObject<T extends Object>(obj: T): Partial<T>; | ||
/** | ||
* Tries to parse the given JSON string into a JavaScript Value. | ||
* @param json The JSON to parse. | ||
*/ | ||
export declare function tryParseJson(json: string): JsonParseResult; | ||
export declare type JsonParseResult = JsonParseSuccess | JsonParseFailure; | ||
export interface JsonParseSuccess { | ||
success: true; | ||
value: any; | ||
} | ||
export interface JsonParseFailure { | ||
success: false; | ||
error: Error; | ||
} | ||
export interface RegexRule { | ||
type: 'allow' | 'deny'; | ||
pattern: string; | ||
} | ||
/** | ||
* Determines if the given value matches the given list of rules. | ||
* @param value The value to test. | ||
* @param rules The rules that the value should be tested against. | ||
*/ | ||
export declare function isStringValid(value: string, rules: RegexRule[]): boolean; | ||
//# sourceMappingURL=Utils.d.ts.map |
66
Utils.js
import { fromByteArray, toByteArray } from 'base64-js'; | ||
import { padStart, sortBy } from 'lodash'; | ||
import { omitBy, padStart, sortBy } from 'lodash'; | ||
import { sha256, hmac } from 'hash.js'; | ||
@@ -237,2 +237,5 @@ /** | ||
} | ||
else if (response.errorCode === 'operation_not_found') { | ||
return 404; | ||
} | ||
else if (response.errorCode === 'session_already_revoked') { | ||
@@ -250,2 +253,5 @@ return 200; | ||
} | ||
else if (response.errorCode === 'invalid_origin') { | ||
return 403; | ||
} | ||
else if (response.errorCode === 'session_expired') { | ||
@@ -281,2 +287,5 @@ return 401; | ||
} | ||
else if (response.errorCode === 'unacceptable_request') { | ||
return 400; | ||
} | ||
else if (response.errorCode === 'address_type_not_supported') { | ||
@@ -297,2 +306,57 @@ return 501; | ||
} | ||
/** | ||
* Clones the given object into a new object that only has non-null and not-undefined properties. | ||
* @param obj The object to cleanup. | ||
*/ | ||
export function cleanupObject(obj) { | ||
return omitBy(obj, (o) => typeof o === 'undefined' || o === null); | ||
} | ||
/** | ||
* Tries to parse the given JSON string into a JavaScript Value. | ||
* @param json The JSON to parse. | ||
*/ | ||
export function tryParseJson(json) { | ||
try { | ||
return { | ||
success: true, | ||
value: JSON.parse(json), | ||
}; | ||
} | ||
catch (err) { | ||
return { | ||
success: false, | ||
error: err, | ||
}; | ||
} | ||
} | ||
/** | ||
* Determines if the given value matches the given list of rules. | ||
* @param value The value to test. | ||
* @param rules The rules that the value should be tested against. | ||
*/ | ||
export function isStringValid(value, rules) { | ||
if (rules.length <= 0) { | ||
return true; | ||
} | ||
const regexRules = rules.map((r) => ({ | ||
type: r.type, | ||
pattern: new RegExp(r.pattern, 'i'), | ||
})); | ||
let good = false; | ||
for (let rule of regexRules) { | ||
if (rule.type === 'allow') { | ||
if (rule.pattern.test(value)) { | ||
good = true; | ||
break; | ||
} | ||
} | ||
else if (rule.type === 'deny') { | ||
if (rule.pattern.test(value)) { | ||
good = false; | ||
break; | ||
} | ||
} | ||
} | ||
return good; | ||
} | ||
//# sourceMappingURL=Utils.js.map |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
320689
78
5654