musare.sh 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. #!/bin/bash
  2. export PATH=/usr/local/bin:/usr/bin:/bin
  3. CYAN='\033[33;36m';
  4. RED='\033[0;31m'
  5. YELLOW='\033[0;93m'
  6. GREEN='\033[0;32m'
  7. NC='\033[0m'
  8. scriptLocation=$(dirname -- "$(readlink -fn -- "$0"; echo x)")
  9. cd "${scriptLocation%x}" || exit
  10. handleServices()
  11. {
  12. validServices=(backend frontend mongo redis)
  13. servicesArray=()
  14. invalidServices=false
  15. for x in "$@"; do
  16. for validService in "${validServices[@]}"
  17. do
  18. if [[ ${validService} =~ (^|[[:space:]])"$x"($|[[:space:]]) ]]; then
  19. for service in "${servicesArray[@]}"
  20. do
  21. if ! [[ "$service" =~ (^|[[:space:]])"$x"($|[[:space:]]) ]]; then
  22. servicesArray+=("$x")
  23. fi
  24. done
  25. else
  26. if [[ $invalidServices == false ]]; then
  27. invalidServices="${x}"
  28. else
  29. invalidServices="${invalidServices} ${x}"
  30. fi
  31. fi
  32. done
  33. done
  34. if [[ $invalidServices == false && ${#servicesArray[@]} -gt 0 ]]; then
  35. echo "1|" "${servicesArray[@]}"
  36. elif [[ $invalidServices == false ]]; then
  37. echo "1|all"
  38. else
  39. echo "0|Invalid Service(s): ${invalidServices}"
  40. fi
  41. }
  42. if [[ -x "$(command -v docker)" && -x "$(command -v docker-compose)" ]]; then
  43. case $1 in
  44. start)
  45. echo -e "${CYAN}Musare | Start Services${NC}"
  46. servicesString=$(handleServices "${@:2}")
  47. if [[ ${servicesString:0:1} == 1 && ${servicesString:2:4} == "all" ]]; then
  48. docker-compose up -d
  49. elif [[ ${servicesString:0:1} == 1 ]]; then
  50. docker-compose up -d "${servicesString:2}"
  51. else
  52. echo -e "${RED}${servicesString:2}\n${YELLOW}Usage: $(basename "$0") start [backend, frontend, mongo, redis]${NC}"
  53. fi
  54. ;;
  55. stop)
  56. echo -e "${CYAN}Musare | Stop Services${NC}"
  57. servicesString=$(handleServices "${@:2}")
  58. if [[ ${servicesString:0:1} == 1 && ${servicesString:2:4} == "all" ]]; then
  59. docker-compose stop
  60. elif [[ ${servicesString:0:1} == 1 ]]; then
  61. docker-compose stop "${servicesString:2}"
  62. else
  63. echo -e "${RED}${servicesString:2}\n${YELLOW}Usage: $(basename "$0") stop [backend, frontend, mongo, redis]${NC}"
  64. fi
  65. ;;
  66. restart)
  67. echo -e "${CYAN}Musare | Restart Services${NC}"
  68. servicesString=$(handleServices "${@:2}")
  69. if [[ ${servicesString:0:1} == 1 && ${servicesString:2:4} == "all" ]]; then
  70. docker-compose stop
  71. docker-compose up -d
  72. elif [[ ${servicesString:0:1} == 1 ]]; then
  73. docker-compose stop "${servicesString:2}"
  74. docker-compose up -d "${servicesString:2}"
  75. else
  76. echo -e "${RED}${servicesString:2}\n${YELLOW}Usage: $(basename "$0") restart [backend, frontend, mongo, redis]${NC}"
  77. fi
  78. ;;
  79. build)
  80. echo -e "${CYAN}Musare | Build Services${NC}"
  81. servicesString=$(handleServices "${@:2}")
  82. if [[ ${servicesString:0:1} == 1 && ${servicesString:2:4} == "all" ]]; then
  83. docker-compose build
  84. elif [[ ${servicesString:0:1} == 1 ]]; then
  85. docker-compose build "${servicesString:2}"
  86. else
  87. echo -e "${RED}${servicesString:2}\n${YELLOW}Usage: $(basename "$0") build [backend, frontend, mongo, redis]${NC}"
  88. fi
  89. ;;
  90. reset)
  91. echo -e "${CYAN}Musare | Reset Services${NC}"
  92. servicesString=$(handleServices "${@:2}")
  93. if [[ ${servicesString:0:1} == 1 && ${servicesString:2:4} == "all" ]]; then
  94. echo -e "${GREEN}Are you sure you want to reset all data? ${YELLOW}[y,n]: ${NC}"
  95. read -r confirm
  96. if [[ "${confirm}" == y* ]]; then
  97. docker-compose stop
  98. docker-compose rm -v --force
  99. if [[ -d ".redis" ]]; then
  100. rm -rf .redis
  101. fi
  102. if [[ -d ".db" ]]; then
  103. rm -rf .db
  104. fi
  105. else
  106. echo -e "${RED}Cancelled reset${NC}"
  107. fi
  108. elif [[ ${servicesString:0:1} == 1 ]]; then
  109. echo -e "${GREEN}Are you sure you want to reset all data for $(echo "${servicesString:2}" | tr ' ' ',')? ${YELLOW}[y,n]: ${NC}"
  110. read -r confirm
  111. if [[ "${confirm}" == y* ]]; then
  112. docker-compose stop "${servicesString:2}"
  113. docker-compose rm -v --force "${servicesString:2}"
  114. if [[ "${servicesString:2}" == *redis* && -d ".redis" ]]; then
  115. rm -rf .redis
  116. fi
  117. if [[ "${servicesString:2}" == *mongo* && -d ".db" ]]; then
  118. rm -rf .db
  119. fi
  120. else
  121. echo -e "${RED}Cancelled reset${NC}"
  122. fi
  123. else
  124. echo -e "${RED}${servicesString:2}\n${YELLOW}Usage: $(basename "$0") build [backend, frontend, mongo, redis]${NC}"
  125. fi
  126. ;;
  127. attach)
  128. echo -e "${CYAN}Musare | Attach${NC}"
  129. if [[ $2 == "backend" ]]; then
  130. containerId=$(docker-compose ps -q backend)
  131. if [[ -z $containerId ]]; then
  132. echo -e "${RED}Error: Backend offline, please start to attach.${NC}"
  133. else
  134. docker attach "$containerId"
  135. fi
  136. else
  137. echo -e "${RED}Invalid service $2\n${YELLOW}Usage: $(basename "$0") attach backend${NC}"
  138. fi
  139. ;;
  140. eslint)
  141. echo -e "${CYAN}Musare | ESLint${NC}"
  142. fix=""
  143. if [[ $2 == "fix" || $3 == "fix" || $2 == "--fix" || $3 == "--fix" ]]; then
  144. fix="--fix"
  145. echo -e "${GREEN}Auto-fix enabled${NC}"
  146. fi
  147. case $2 in
  148. frontend)
  149. docker-compose exec frontend npx eslint app/src --ext .js,.vue $fix
  150. ;;
  151. backend)
  152. docker-compose exec backend npx eslint app/logic $fix
  153. ;;
  154. ""|fix|--fix)
  155. docker-compose exec frontend npx eslint app/src --ext .js,.vue $fix
  156. docker-compose exec backend npx eslint app/logic $fix
  157. ;;
  158. *)
  159. echo -e "${RED}Invalid service $2\n${YELLOW}Usage: $(basename "$0") eslint [backend, frontend] [fix]${NC}"
  160. ;;
  161. esac
  162. ;;
  163. update)
  164. echo -e "${CYAN}Musare | Update${NC}"
  165. git fetch
  166. if [[ $(git rev-parse HEAD) == $(git rev-parse @\{u\}) ]]; then
  167. echo -e "${GREEN}Already up to date${NC}"
  168. else
  169. dbChange=$(git log --name-only --oneline HEAD..origin/"$(git rev-parse --abbrev-ref HEAD)" | grep "backend/logic/db/schemas")
  170. fcChange=$(git log --name-only --oneline HEAD..origin/"$(git rev-parse --abbrev-ref HEAD)" | grep "frontend/dist/config/template.json")
  171. bcChange=$(git log --name-only --oneline HEAD..origin/"$(git rev-parse --abbrev-ref HEAD)" | grep "backend/config/template.json")
  172. if [[ ( $2 == "auto" && -z $dbChange && -z $fcChange && -z $bcChange ) || -z $2 ]]; then
  173. echo -e "${CYAN}Updating...${NC}"
  174. git pull
  175. docker-compose build
  176. docker-compose stop
  177. docker-compose up -d
  178. echo -e "${GREEN}Updated!${NC}"
  179. if [[ -n $dbChange ]]; then
  180. echo -e "${RED}Database schema has changed, please run migration!${NC}"
  181. fi
  182. if [[ -n $fcChange ]]; then
  183. echo -e "${RED}Frontend config has changed, please update!${NC}"
  184. fi
  185. if [[ -n $bcChange ]]; then
  186. echo -e "${RED}Backend config has changed, please update!${NC}"
  187. fi
  188. elif [[ $2 == "auto" ]]; then
  189. echo -e "${RED}Auto Update Failed! Database and/or config has changed!${NC}"
  190. fi
  191. fi
  192. ;;
  193. logs)
  194. echo -e "${CYAN}Musare | Logs${NC}"
  195. docker-compose logs "${@:2}"
  196. ;;
  197. backup)
  198. echo -e "${CYAN}Musare | Backup${NC}"
  199. if [[ -f .env ]]; then
  200. # shellcheck disable=SC1091
  201. source .env
  202. if [[ ! -d "${scriptLocation%x}/backups" ]]; then
  203. echo -e "${YELLOW}Creating backup directory at ${scriptLocation%x}/backups${NC}"
  204. mkdir "${scriptLocation%x}/backups"
  205. fi
  206. echo -e "${YELLOW}Creating backup at ${scriptLocation%x}/backups/musare-$(date +"%Y-%m-%d-%s").dump${NC}"
  207. docker-compose exec -T mongo sh -c "mongodump --authenticationDatabase musare -u ${MONGO_USER_USERNAME} -p ${MONGO_USER_PASSWORD} -d musare --archive" > "${scriptLocation%x}/backups/musare-$(date +"%Y-%m-%d-%s").dump"
  208. else
  209. echo -e "${RED}Error: .env does not exist${NC}"
  210. fi
  211. ;;
  212. restore)
  213. echo -e "${CYAN}Musare | Restore${NC}"
  214. if [[ -f .env ]]; then
  215. # shellcheck disable=SC1091
  216. source .env
  217. if [[ -z $2 ]]; then
  218. echo -e "${GREEN}Please enter the full path of the dump you wish to restore: ${NC}"
  219. read -r restoreFile
  220. else
  221. restoreFile=$2
  222. fi
  223. if [[ -z ${restoreFile} ]]; then
  224. echo -e "${RED}Error: no restore path given, cancelled restoration.${NC}"
  225. elif [[ -d ${restoreFile} ]]; then
  226. echo -e "${RED}Error: restore path given is a directory, cancelled restoration.${NC}"
  227. elif [[ ! -f ${restoreFile} ]]; then
  228. echo -e "${RED}Error: no file at restore path given, cancelled restoration.${NC}"
  229. else
  230. docker-compose exec -T mongo sh -c "mongorestore --authenticationDatabase musare -u ${MONGO_USER_USERNAME} -p ${MONGO_USER_PASSWORD} --archive" < "${restoreFile}"
  231. fi
  232. else
  233. echo -e "${RED}Error: .env does not exist${NC}"
  234. fi
  235. ;;
  236. admin)
  237. echo -e "${CYAN}Musare | Add Admin${NC}"
  238. if [[ -f .env ]]; then
  239. # shellcheck disable=SC1091
  240. source .env
  241. if [[ $2 == "add" ]]; then
  242. if [[ -z $3 ]]; then
  243. echo -e "${GREEN}Please enter the username of the user you wish to make an admin: ${NC}"
  244. read -r adminUser
  245. else
  246. adminUser=$3
  247. fi
  248. if [[ -z $adminUser ]]; then
  249. echo -e "${RED}Error: Username for new admin not provided.${NC}"
  250. else
  251. docker-compose exec mongo mongo musare -u "${MONGO_USER_USERNAME}" -p "${MONGO_USER_PASSWORD}" --eval "db.users.update({username: '${adminUser}'}, {\$set: {role: 'admin'}})"
  252. fi
  253. elif [[ $2 == "remove" ]]; then
  254. if [[ -z $3 ]]; then
  255. echo -e "${GREEN}Please enter the username of the user you wish to remove as admin: ${NC}"
  256. read -r adminUser
  257. else
  258. adminUser=$3
  259. fi
  260. if [[ -z $adminUser ]]; then
  261. echo -e "${RED}Error: Username for new admin not provided.${NC}"
  262. else
  263. docker-compose exec mongo mongo musare -u "${MONGO_USER_USERNAME}" -p "${MONGO_USER_PASSWORD}" --eval "db.users.update({username: '${adminUser}'}, {\$set: {role: 'default'}})"
  264. fi
  265. else
  266. echo -e "${RED}Invalid command $2\n${YELLOW}Usage: $(basename "$0") admin [add,remove] username${NC}"
  267. fi
  268. else
  269. echo -e "${RED}Error: .env does not exist${NC}"
  270. fi
  271. ;;
  272. "")
  273. echo -e "${CYAN}Musare | Available Commands${NC}"
  274. echo -e "${YELLOW}start - Start services${NC}"
  275. echo -e "${YELLOW}stop - Stop services${NC}"
  276. echo -e "${YELLOW}restart - Restart services${NC}"
  277. echo -e "${YELLOW}logs - View logs for services${NC}"
  278. echo -e "${YELLOW}update - Update Musare${NC}"
  279. echo -e "${YELLOW}attach backend - Attach to backend service${NC}"
  280. echo -e "${YELLOW}build - Build services${NC}"
  281. echo -e "${YELLOW}eslint - Run eslint on frontend and/or backend${NC}"
  282. echo -e "${YELLOW}backup - Backup database data to file${NC}"
  283. echo -e "${YELLOW}restore - Restore database data from backup file${NC}"
  284. echo -e "${YELLOW}reset - Reset service data${NC}"
  285. echo -e "${YELLOW}admin [add,remove] - Assign/unassign admin role to/from a user${NC}"
  286. ;;
  287. *)
  288. echo -e "${CYAN}Musare${NC}"
  289. echo -e "${RED}Error: Invalid Command $1${NC}"
  290. echo -e "${CYAN}Available Commands:${NC}"
  291. echo -e "${YELLOW}start - Start services${NC}"
  292. echo -e "${YELLOW}stop - Stop services${NC}"
  293. echo -e "${YELLOW}restart - Restart services${NC}"
  294. echo -e "${YELLOW}logs - View logs for services${NC}"
  295. echo -e "${YELLOW}update - Update Musare${NC}"
  296. echo -e "${YELLOW}attach backend - Attach to backend service${NC}"
  297. echo -e "${YELLOW}build - Build services${NC}"
  298. echo -e "${YELLOW}eslint - Run eslint on frontend and/or backend${NC}"
  299. echo -e "${YELLOW}backup - Backup database data to file${NC}"
  300. echo -e "${YELLOW}restore - Restore database data from backup file${NC}"
  301. echo -e "${YELLOW}reset - Reset service data${NC}"
  302. echo -e "${YELLOW}admin [add,remove] - Assign/unassign admin role to/from a user${NC}"
  303. ;;
  304. esac
  305. elif [[ -x "$(command -v docker)" && ! -x "$(command -v docker-compose)" ]]; then
  306. echo -e "${RED}Error: docker-compose not installed.${NC}"
  307. elif [[ ! -x "$(command -v docker)" && -x "$(command -v docker-compose)" ]]; then
  308. echo -e "${RED}Error: docker not installed.${NC}"
  309. else
  310. echo -e "${RED}Error: docker and docker-compose not installed.${NC}"
  311. fi