Skip to content
This repository has been archived by the owner on Apr 19, 2023. It is now read-only.

Commit

Permalink
✨ Check if username is available
Browse files Browse the repository at this point in the history
  • Loading branch information
AnandChowdhary committed Jun 22, 2019
1 parent 42cc634 commit 20009b7
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 6 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "staart",
"version": "1.0.28",
"version": "1.0.29",
"main": "index.js",
"repository": "[email protected]:AnandChowdhary/staart.git",
"author": "Anand Chowdhary <[email protected]>",
Expand Down
2 changes: 1 addition & 1 deletion setup/controllers.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,6 @@ recursive(path.join(SRC, "..", "static"))
.then(() => {
fs.writeFileSync(path.join(SRC, "app.ts"), server);
console.log("✅ Generated app.ts file");
console.log(" Compiling TypeScript");
console.log(" Compiling TypeScript");
process.exit(0);
});
6 changes: 6 additions & 0 deletions src/crud/organization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,12 @@ export const updateOrganization = async (
) => {
organization.updatedAt = dateToDateTime(new Date());
organization = removeReadOnlyValues(organization);
if (organization.username) {
const currentOwner = await getOrganizationIdFromUsername(
organization.username
);
if (currentOwner != id) throw new Error(ErrorCode.USERNAME_EXISTS);
}
deleteItemFromCache(CacheCategories.ORGANIZATION, id);
return await query(
`UPDATE organizations SET ${setValues(organization)} WHERE id = ?`,
Expand Down
41 changes: 38 additions & 3 deletions src/crud/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export const createUser = async (user: User) => {
user.prefersColorSchemeDark = user.prefersColorSchemeDark || false;
user.profilePicture =
user.profilePicture ||
`https://ui-avatars.com/api/?bold=true&name=${user.name}`;
`https://api.adorable.io/avatars/285/${md5(user.name)}.png`;
user.createdAt = new Date();
user.updatedAt = user.createdAt;
// Create user
Expand Down Expand Up @@ -94,17 +94,32 @@ export const updateUser = async (id: number, user: KeyValue) => {
user.updatedAt = dateToDateTime(new Date());
if (user.password) user.password = await hash(user.password, 8);
user = removeReadOnlyValues(user);
// If you're updating your primary email, your Gravatar should reflect it
if (user.primaryEmail) {
const originalUser = await getUser(id);
if ((originalUser.profilePicture || "").includes("ui-avatars.com")) {
if ((originalUser.profilePicture || "").includes("api.adorable.io")) {
const emailDetails = await getEmail(user.primaryEmail);
user.profilePicture = `https://www.gravatar.com/avatar/${md5(
emailDetails.email
)}?d=${encodeURIComponent(
`https://ui-avatars.com/api/?bold=true&name=${originalUser.name}`
`https://api.adorable.io/avatars/285/${md5(originalUser.name)}.png`
)}`;
}
}
// If you're updating your username, make sure it's available
if (user.username) {
const originalUser = await getUser(id);
let usernameOwner: User | undefined = undefined;
try {
usernameOwner = await getUserByUsername(user.username);
} catch (error) {}
if (
usernameOwner &&
usernameOwner.id &&
usernameOwner.id != originalUser.id
)
throw new Error(ErrorCode.USERNAME_EXISTS);
}
deleteItemFromCache(CacheCategories.USER, id);
return await query(`UPDATE users SET ${setValues(user)} WHERE id = ?`, [
...Object.values(user),
Expand Down Expand Up @@ -149,6 +164,26 @@ export const getUserApprovedLocations = async (userId: number) => {
]);
};

/**
* Get a user by their username
*/
export const getUserByUsername = async (username: string) => {
return ((await query("SELECT * FROM users WHERE username = ? LIMIT 1", [
username
])) as User[])[0];
};

/**
* Get a user by their username
*/
export const checkUsernameAvailability = async (username: string) => {
try {
const user = await getUserByUsername(username);
if (user && user.id) return false;
} catch (error) {}
return true;
};

/**
* Delete all approved locations for a user
*/
Expand Down
1 change: 1 addition & 0 deletions src/interfaces/enum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ export enum ErrorCode {
MISSING_FIELD = "422/missing-field",
INVALID_INPUT = "422/invalid-input",
EMAIL_EXISTS = "422/email-exists",
USERNAME_EXISTS = "422/username-exists",
USER_NOT_FOUND = "404/user-not-found",
MEMBERSHIP_NOT_FOUND = "404/membership-not-found",
ORGANIZATION_NOT_FOUND = "404/organization-not-found",
Expand Down
5 changes: 4 additions & 1 deletion src/rest/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import {
getUser,
addApprovedLocation,
getUserBackupCode,
updateBackupCode
updateBackupCode,
checkUsernameAvailability
} from "../crud/user";
import { InsertResult } from "../interfaces/mysql";
import {
Expand Down Expand Up @@ -106,6 +107,8 @@ export const register = async (
) => {
if (email) await checkIfNewEmail(email);
if (!user.username) user.username = createSlug(user.name);
if (!(await checkUsernameAvailability(user.username)))
throw new Error(ErrorCode.USERNAME_EXISTS);
const result = <InsertResult>await createUser(user);
const userId = result.insertId;
// Set email
Expand Down

0 comments on commit 20009b7

Please sign in to comment.