fix(striker-ui-api): add create and update user endpoints

main
Tsu-ba-me 2 years ago
parent b080d319af
commit c5015bf43f
  1. 64
      striker-ui-api/src/lib/request_handlers/user/createUser.ts
  2. 7
      striker-ui-api/src/lib/request_handlers/user/deleteUser.ts
  3. 2
      striker-ui-api/src/lib/request_handlers/user/index.ts
  4. 136
      striker-ui-api/src/lib/request_handlers/user/updateUser.ts
  5. 9
      striker-ui-api/src/routes/user.ts
  6. 15
      striker-ui-api/src/types/ApiUser.d.ts

@ -0,0 +1,64 @@
import assert from 'assert';
import { RequestHandler } from 'express';
import { REP_PEACEFUL_STRING, REP_UUID } from '../../consts';
import { insertOrUpdateUser, query } from '../../accessModule';
import { sanitize } from '../../sanitize';
import { openssl, stderr, stdoutVar } from '../../shell';
export const createUser: RequestHandler<
unknown,
CreateUserResponseBody,
CreateUserRequestBody
> = async (request, response) => {
const { body: { password: rPassword, userName: rUserName } = {} } = request;
const password = sanitize(rPassword, 'string', {
fallback: openssl('rand', '-base64', '12').trim(),
});
const userName = sanitize(rUserName, 'string', { modifierType: 'sql' });
stdoutVar({ password, userName }, 'Create user with params: ');
try {
assert(
REP_PEACEFUL_STRING.test(password),
`Password must be a peaceful string; got: [${password}]`,
);
assert(
REP_PEACEFUL_STRING.test(userName),
`User name must be a peaceful string; got: [${userName}]`,
);
const [[userCount]]: [[number]] = await query(
`SELECT COUNT(user_uuid) FROM users WHERE user_name = '${userName}';`,
);
assert(userCount === 0, `User name [${userName}] already used`);
} catch (error) {
stderr(`Failed to assert value when creating user; CAUSE: ${error}`);
return response.status(400).send();
}
try {
const result = await insertOrUpdateUser({
file: __filename,
user_name: userName,
user_password_hash: password,
});
assert(
REP_UUID.test(result),
`Insert or update failed with result [${result}]`,
);
} catch (error) {
stderr(`Failed to record user to database; CAUSE: ${error}`);
return response.status(500).send();
}
return response.status(201).send({ password });
};

@ -9,7 +9,7 @@ import { sanitize } from '../../sanitize';
import { stderr, stdoutVar } from '../../shell';
export const deleteUser: RequestHandler<
DeleteUserParamsDictionary,
UserParamsDictionary,
undefined,
DeleteUserRequestBody
> = async (request, response) => {
@ -45,7 +45,10 @@ export const deleteUser: RequestHandler<
const wcode = await write(
`UPDATE users
SET user_algorithm = '${DELETED}'
WHERE user_uuid IN (${join(ulist)});`,
WHERE user_uuid IN (${join(ulist, {
elementWrapper: "'",
separator: ',',
})});`,
);
assert(wcode === 0, `Write exited with code ${wcode}`);

@ -1,2 +1,4 @@
export * from './createUser';
export * from './deleteUser';
export * from './getUser';
export * from './updateUser';

@ -0,0 +1,136 @@
import assert from 'assert';
import { RequestHandler } from 'express';
import { REP_PEACEFUL_STRING, REP_UUID } from '../../consts';
import { encrypt, query, write } from '../../accessModule';
import { sanitize } from '../../sanitize';
import { stderr, stdoutVar } from '../../shell';
export const updateUser: RequestHandler<
UserParamsDictionary,
undefined,
UpdateUserRequestBody
> = async (request, response) => {
const {
body: { password: rPassword, userName: rUserName } = {},
params: { userUuid },
} = request;
const password = sanitize(rPassword, 'string');
const userName = sanitize(rUserName, 'string', { modifierType: 'sql' });
stdoutVar({ password, userName }, `Update user ${userUuid} with params: `);
try {
if (password.length) {
assert(
REP_PEACEFUL_STRING.test(password),
`Password must be a valid peaceful string; got: [${password}]`,
);
}
if (userName.length) {
assert(
REP_PEACEFUL_STRING.test(userName),
`User name must be a peaceful string; got: [${userName}]`,
);
}
assert(
REP_UUID.test(userUuid),
`User UUID must be a valid UUIDv4; got: [${userUuid}]`,
);
const [[existingUserName]]: [[string]] = await query(
`SELECT user_name FROM users WHERE user_uuid = '${userUuid}';`,
);
assert(existingUserName !== 'admin' || userName, 'Cannot ');
} catch (error) {
stderr(`Assert failed when update user; CAUSE: ${error}`);
return response.status(400).send();
}
let existingUser: [
[
user_name: string,
user_password_hash: string,
user_salt: string,
user_algorithm: string,
user_hash_count: string,
],
];
try {
existingUser = await query(
`SELECT
user_name,
user_password_hash,
user_salt,
user_algorithm,
user_hash_count
FROM users
WHERE user_uuid = '${userUuid}'
ORDER BY modified_date DESC
LIMIT 1;`,
);
} catch (error) {
stderr(`Failed to find existing user ${userUuid}; CAUSE: ${error}`);
return response.status(500).send();
}
if (existingUser.length !== 1) {
return response.status(404).send();
}
const [[xUserName, xPasswordHash, xSalt, xAlgorithm, xHashCount]] =
existingUser;
const assigns: string[] = [];
if (password.length) {
let passwordHash: string;
try {
({ user_password_hash: passwordHash } = await encrypt({
algorithm: xAlgorithm,
hash_count: xHashCount,
password,
salt: xSalt,
}));
} catch (error) {
stderr(`Encrypt failed when update user; CAUSE ${error}`);
return response.status(500).send();
}
if (passwordHash !== xPasswordHash) {
assigns.push(`user_password_hash = '${passwordHash}'`);
}
}
if (userName.length && userName !== xUserName) {
assigns.push(`user_name = '${userName}'`);
}
if (assigns.length) {
try {
const wcode = await write(
`UPDATE users SET ${assigns.join(
',',
)} WHERE user_uuid = '${userUuid}';`,
);
assert(wcode === 0, `Update users failed with code: ${wcode}`);
} catch (error) {
stderr(`Failed to record user changes to database; CAUSE: ${error}`);
return response.status(500).send();
}
}
return response.send();
};

@ -1,11 +1,18 @@
import express from 'express';
import { deleteUser, getUser } from '../lib/request_handlers/user';
import {
createUser,
deleteUser,
getUser,
updateUser,
} from '../lib/request_handlers/user';
const router = express.Router();
router
.get('/', getUser)
.post('/', createUser)
.put('/:userUuid', updateUser)
.delete('/', deleteUser)
.delete('/:userUuid', deleteUser);

@ -1,7 +1,18 @@
type DeleteUserParamsDictionary = {
userUuid: string;
type CreateUserRequestBody = {
password?: string;
userName: string;
};
type CreateUserResponseBody = {
password: string;
};
type DeleteUserRequestBody = {
uuids?: string[];
};
type UpdateUserRequestBody = Partial<CreateUserRequestBody>;
type UserParamsDictionary = {
userUuid: string;
};

Loading…
Cancel
Save