381 lines
8.9 KiB
TypeScript
381 lines
8.9 KiB
TypeScript
import { Request, Response } from "express";
|
|
import logger from "../logger/logger";
|
|
import User from "../models/user";
|
|
import {
|
|
isAccountNameValid,
|
|
isPasswordValid,
|
|
isUsernameValid,
|
|
} from "../validator/validator";
|
|
import {
|
|
CALENDAR_MAX_FUTURE_BOOKING_DAYS,
|
|
CALENDAR_MAX_SERVICE_DURATION,
|
|
CALENDAR_MIN_EARLIEST_BOOKING_TIME,
|
|
Roles,
|
|
} from "../utils/constants";
|
|
import {
|
|
decodeBase64,
|
|
getUserSession,
|
|
hashPassword,
|
|
matchPassword,
|
|
newStoreId,
|
|
newUserId,
|
|
saveSession,
|
|
} from "../utils/utils";
|
|
import Store from "../models/store";
|
|
|
|
export async function SignUp(req: Request, res: Response) {
|
|
try {
|
|
let { username, accountName, password } = req.body;
|
|
|
|
// validate request
|
|
|
|
if (!username || !accountName || !password) {
|
|
return res.status(400).send({ err: "invalid request" });
|
|
}
|
|
|
|
if (!isUsernameValid(username)) {
|
|
return res.status(400).send({ err: "invalid request" });
|
|
}
|
|
|
|
if (!isAccountNameValid(accountName)) {
|
|
return res.status(400).send({ err: "invalid request" });
|
|
}
|
|
|
|
accountName = accountName.toLowerCase();
|
|
|
|
// check if user already exists
|
|
|
|
const existingUser = await User.findOne({
|
|
where: {
|
|
account_name: accountName,
|
|
},
|
|
});
|
|
|
|
if (existingUser) {
|
|
logger.debug(
|
|
"User already exists with this accountName: %s",
|
|
accountName
|
|
);
|
|
return res.status(400).send({ err: "invalid request" });
|
|
}
|
|
|
|
// decode password
|
|
|
|
const decodedPassword = decodeBase64(password);
|
|
|
|
if (!isPasswordValid(decodedPassword)) {
|
|
logger.debug("Password is not valid");
|
|
return res.status(400).send({ err: "invalid request" });
|
|
}
|
|
|
|
// hash password
|
|
|
|
const hashedPassword = await hashPassword(decodedPassword);
|
|
|
|
// create store
|
|
|
|
let userId = newUserId();
|
|
|
|
Store.create({
|
|
store_id: newStoreId(),
|
|
owner_user_id: userId,
|
|
name: username,
|
|
calendar_max_future_booking_days: CALENDAR_MAX_FUTURE_BOOKING_DAYS,
|
|
calendar_min_earliest_booking_time: CALENDAR_MIN_EARLIEST_BOOKING_TIME,
|
|
//calendar_using_primary_calendar: CALENDAR_USING_PRIMARY_CALENDAR,
|
|
calendar_max_service_duration: CALENDAR_MAX_SERVICE_DURATION,
|
|
})
|
|
.then(async (store) => {
|
|
logger.debug(
|
|
"Store created with storeId: %s storeName: %s",
|
|
store.store_id,
|
|
store.name
|
|
);
|
|
|
|
// create user
|
|
|
|
await User.create({
|
|
user_id: userId,
|
|
store_id: store.store_id,
|
|
role: Roles.Master,
|
|
account_name: accountName,
|
|
username: username,
|
|
password: hashedPassword,
|
|
language: "en", // TODO: get language from request
|
|
analytics_enabled: true,
|
|
})
|
|
.then((user) => {
|
|
logger.debug(
|
|
"User created with accountName: %s username: %s",
|
|
user.account_name,
|
|
user.username
|
|
);
|
|
|
|
// create session
|
|
saveSession(res, user.user_id, user.username);
|
|
})
|
|
.catch((err) => {
|
|
logger.error(err);
|
|
res.status(500).send({ err: "invalid request" });
|
|
});
|
|
})
|
|
.catch((err) => {
|
|
logger.error(err);
|
|
res.status(500).send({ err: "invalid request" });
|
|
});
|
|
} catch (error) {
|
|
logger.error(error);
|
|
res.status(500).send({ err: "invalid request" });
|
|
}
|
|
}
|
|
|
|
export async function Login(req: Request, res: Response) {
|
|
try {
|
|
let { accountName, password } = req.body;
|
|
|
|
// validate request
|
|
|
|
if (!accountName || !password) {
|
|
return res.status(400).send({ err: "invalid request" });
|
|
}
|
|
|
|
accountName = accountName.toLowerCase();
|
|
|
|
if (!isAccountNameValid(accountName)) {
|
|
return res.status(400).send({ err: "invalid request" });
|
|
}
|
|
|
|
// check if user exists
|
|
const user = await User.findOne({
|
|
where: {
|
|
account_name: accountName,
|
|
},
|
|
});
|
|
|
|
if (!user) {
|
|
logger.debug(
|
|
"User does not exist with this accountName: %s",
|
|
accountName
|
|
);
|
|
return res.status(400).send({ err: "invalid request" });
|
|
}
|
|
|
|
// decode password
|
|
|
|
const decodedPassword = decodeBase64(password);
|
|
|
|
if (!isPasswordValid(decodedPassword)) {
|
|
logger.debug("Password is not valid");
|
|
return res.status(400).send({ err: "invalid request" });
|
|
}
|
|
|
|
// compare password
|
|
|
|
const match = await matchPassword(decodedPassword, user.password);
|
|
|
|
if (!match) {
|
|
logger.debug("Password is not valid");
|
|
return res.status(400).send({ err: "invalid request" });
|
|
}
|
|
|
|
// create session
|
|
saveSession(res, user.user_id, user.username);
|
|
} catch (error) {
|
|
logger.error(error);
|
|
res.status(500).send({ err: "invalid request" });
|
|
}
|
|
}
|
|
|
|
export async function Logout(req: Request, res: Response) {
|
|
try {
|
|
const session = await getUserSession(req);
|
|
|
|
if (!session) {
|
|
return res.status(401).send({ err: "unauthorized" });
|
|
}
|
|
|
|
await session.destroy();
|
|
|
|
res.status(200).send({ msg: "logout successful" });
|
|
} catch (error) {
|
|
logger.error(error);
|
|
res.status(500).send({ err: "invalid request" });
|
|
}
|
|
}
|
|
|
|
export async function GetUser(req: Request, res: Response) {
|
|
try {
|
|
const session = await getUserSession(req);
|
|
|
|
if (!session) {
|
|
return res.status(401).send({ err: "unauthorized" });
|
|
}
|
|
|
|
const user = await User.findOne({
|
|
where: {
|
|
user_id: session.user_id,
|
|
},
|
|
attributes: [
|
|
"user_id",
|
|
"username",
|
|
"store_id",
|
|
"language",
|
|
"analytics_enabled",
|
|
],
|
|
});
|
|
|
|
if (!user) {
|
|
return res.status(401).send({ err: "unauthorized" });
|
|
}
|
|
|
|
const stores = await Store.findAll({
|
|
where: {
|
|
owner_user_id: user.user_id,
|
|
},
|
|
attributes: ["store_id", "name"],
|
|
});
|
|
|
|
let respData = {
|
|
user: user,
|
|
stores: stores,
|
|
// only temporary until we have a proper permissions system
|
|
permissions: [] as string[],
|
|
};
|
|
|
|
// if user is not a store master, then check if user is a worker
|
|
if (!stores || stores.length === 0) {
|
|
const store = await Store.findOne({
|
|
where: {
|
|
store_id: user.store_id,
|
|
},
|
|
attributes: ["store_id", "name"],
|
|
});
|
|
|
|
if (!store) {
|
|
return res.status(401).send({ err: "unauthorized" });
|
|
}
|
|
|
|
stores.push(store);
|
|
|
|
respData.stores = stores;
|
|
|
|
respData.permissions.push("calendar");
|
|
} else {
|
|
respData.permissions.push(
|
|
"settings",
|
|
"employees",
|
|
"services",
|
|
"calendar",
|
|
"website"
|
|
);
|
|
}
|
|
|
|
res.status(200).send(respData);
|
|
} catch (error) {
|
|
logger.error(error);
|
|
res.status(500).send({ err: "invalid request" });
|
|
}
|
|
}
|
|
|
|
export async function IsAccountNameAvailable(req: Request, res: Response) {
|
|
try {
|
|
let { accountName } = req.body;
|
|
|
|
// validate request
|
|
|
|
if (!accountName) {
|
|
return res.status(400).send({ err: "invalid request" });
|
|
}
|
|
|
|
accountName = accountName.toLowerCase();
|
|
|
|
if (!isAccountNameValid(accountName)) {
|
|
return res.status(400).send({ err: "invalid request" });
|
|
}
|
|
|
|
// check if user exists
|
|
|
|
const user = await User.findOne({
|
|
where: {
|
|
account_name: accountName,
|
|
},
|
|
});
|
|
|
|
if (user) {
|
|
logger.debug(
|
|
"User already exists with this accountName: %s",
|
|
accountName
|
|
);
|
|
return res.status(400).send({ err: "invalid request" });
|
|
}
|
|
|
|
res.status(200).send({ msg: "account name available" });
|
|
} catch (error) {
|
|
logger.error(error);
|
|
res.status(500).send({ err: "invalid request" });
|
|
}
|
|
}
|
|
|
|
export async function GetUserProfileSettings(req: Request, res: Response) {
|
|
try {
|
|
const session = await getUserSession(req);
|
|
|
|
if (!session) {
|
|
return res.status(401).send({ err: "unauthorized" });
|
|
}
|
|
|
|
const user = await User.findOne({
|
|
where: {
|
|
user_id: session.user_id,
|
|
},
|
|
attributes: ["language", "analytics_enabled"],
|
|
});
|
|
|
|
res.status(200).json(user);
|
|
} catch (error) {
|
|
logger.error(error);
|
|
res.status(500).send({ err: "invalid request" });
|
|
}
|
|
}
|
|
|
|
export async function UpdateUserProfileSettings(req: Request, res: Response) {
|
|
try {
|
|
const { language, analyticsEnabled } = req.body;
|
|
|
|
if (!language && analyticsEnabled === undefined) {
|
|
return res.status(400).send({ err: "invalid request" });
|
|
}
|
|
|
|
const session = await getUserSession(req);
|
|
|
|
if (!session) {
|
|
return res.status(401).send({ err: "unauthorized" });
|
|
}
|
|
|
|
const user = await User.findOne({
|
|
where: {
|
|
user_id: session.user_id,
|
|
},
|
|
});
|
|
|
|
if (!user) {
|
|
return res.status(401).send({ err: "unauthorized" });
|
|
}
|
|
|
|
if (language) {
|
|
user.language = language;
|
|
}
|
|
|
|
if (analyticsEnabled !== undefined) {
|
|
user.analytics_enabled = analyticsEnabled;
|
|
}
|
|
|
|
await user.save();
|
|
|
|
res.status(200).send({ msg: "user profile settings updated" });
|
|
} catch (error) {
|
|
logger.error(error);
|
|
res.status(500).send({ err: "invalid request" });
|
|
}
|
|
}
|