login.ejs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. <div id="loginContainer" style="display: none;">
  2. <div id="loginContent">
  3. <form id="loginForm" onsubmit="void(0); return false;">
  4. <img id="loginImageSeal" src="assets/images/WesterosSealCircle.png"/>
  5. <span class="loginSpan" id="loginSubheader">MEMBER LOGIN</span>
  6. <div class="loginFieldContainer">
  7. <svg id="profileSVG" class="loginSVG" viewBox="40 37 65.36 61.43">
  8. <g>
  9. <path d="M86.77,58.12A13.79,13.79,0,1,0,73,71.91,13.79,13.79,0,0,0,86.77,58.12M97,103.67a3.41,3.41,0,0,0,3.39-3.84,27.57,27.57,0,0,0-54.61,0,3.41,3.41,0,0,0,3.39,3.84Z"/>
  10. </g>
  11. </svg>
  12. <span class="loginErrorSpan" id="loginEmailError">* Invalid Value</span>
  13. <input id="loginUsername" class="loginField" type="text" placeholder="EMAIL"/>
  14. </div>
  15. <div class="loginFieldContainer">
  16. <svg id="lockSVG" class="loginSVG" viewBox="40 32 60.36 70.43">
  17. <g>
  18. <path d="M86.16,54a16.38,16.38,0,1,0-32,0H44V102.7H96V54Zm-25.9-3.39a9.89,9.89,0,1,1,19.77,0A9.78,9.78,0,0,1,79.39,54H60.89A9.78,9.78,0,0,1,60.26,50.59ZM70,96.2a6.5,6.5,0,0,1-6.5-6.5,6.39,6.39,0,0,1,3.1-5.4V67h6.5V84.11a6.42,6.42,0,0,1,3.39,5.6A6.5,6.5,0,0,1,70,96.2Z"/>
  19. </g>
  20. </svg>
  21. <span class="loginErrorSpan" id="loginPasswordError">* Required</span>
  22. <input id="loginPassword" class="loginField" type="password" placeholder="PASSWORD"/>
  23. </div>
  24. <div id="loginOptions">
  25. <span class="loginSpanDim">
  26. <a href="https://help.mojang.com/customer/en/portal/articles/329524-change-or-forgot-password">forgot password?</a>
  27. </span>
  28. <label id="checkmarkContainer">
  29. <input id="loginRememberOption" type="checkbox" checked>
  30. <span id="loginRememberText" class="loginSpanDim">remember me?</span>
  31. <span class="loginCheckmark"></span>
  32. </label>
  33. </div>
  34. <button id="loginButton" disabled>
  35. <div id="loginButtonContent">
  36. LOGIN
  37. <svg id="loginSVG" viewBox="0 0 24.87 13.97">
  38. <defs>
  39. <style>.arrowLine{fill:none;stroke:#FFF;stroke-width:2px;transition: 0.25s ease;}</style>
  40. </defs>
  41. <polyline class="arrowLine" points="0.71 13.26 12.56 1.41 24.16 13.02"/>
  42. </svg>
  43. <div class="circle-loader">
  44. <div class="checkmark draw"></div>
  45. </div>
  46. <!--<div class="spinningCircle" id="loginSpinner"></div>-->
  47. </div>
  48. </button>
  49. <div id="loginDisclaimer">
  50. <span class="loginSpanDim" id="loginRegisterSpan">
  51. <a href="https://minecraft.net/en-us/store/minecraft/">Need an Account?</a>
  52. </span>
  53. <p class="loginDisclaimerText">Your password is sent directly to mojang and never stored.</p>
  54. <p class="loginDisclaimerText">WesterosCraft is not affiliated with Mojang AB.</p>
  55. </div>
  56. </form>
  57. </div>
  58. <script type="application/javascript">
  59. //const validEmail = /^(([^<>()\[\]\.,;:\s@\"]+(\.[^<>()\[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i
  60. // Validation Regexes.
  61. const validUsername = /^[a-zA-Z0-9_]{1,16}$/
  62. const basicEmail = /^\S+@\S+\.\S+$/
  63. // DOM cache.
  64. const loginContainer = document.getElementById('loginContainer')
  65. const loginErrorTitle = document.getElementById('loginErrorTitle')
  66. const loginErrorDesc = document.getElementById('loginErrorDesc')
  67. const loginErrorAcknowledge = document.getElementById('loginErrorAcknowledge')
  68. const loginEmailError = document.getElementById('loginEmailError')
  69. const loginUsername = document.getElementById('loginUsername')
  70. const loginPasswordError = document.getElementById('loginPasswordError')
  71. const loginPassword = document.getElementById('loginPassword')
  72. const checkmarkContainer = document.getElementById('checkmarkContainer')
  73. const loginRememberOption = document.getElementById('loginRememberOption')
  74. const loginButton = document.getElementById('loginButton')
  75. // Control variables.
  76. let lu = false, lp = false
  77. // Show error element.
  78. function showError(element, value){
  79. element.innerHTML = value
  80. element.style.opacity = 1
  81. }
  82. // Shake error element.
  83. function shakeError(element){
  84. if(element.style.opacity == 1){
  85. element.classList.remove('shake')
  86. void element.offsetWidth
  87. element.classList.add('shake')
  88. }
  89. }
  90. // Validate email field is neither empty nor invalid.
  91. function validateEmail(value){
  92. if(value){
  93. if(!basicEmail.test(value) && !validUsername.test(value)){
  94. showError(loginEmailError, '* Invalid Value')
  95. loginDisabled(true)
  96. lu = false
  97. } else {
  98. loginEmailError.style.opacity = 0
  99. lu = true
  100. if(lp){
  101. loginDisabled(false)
  102. }
  103. }
  104. } else {
  105. lu = false
  106. showError(loginEmailError, '* Required')
  107. loginDisabled(true)
  108. }
  109. }
  110. // Validate password field is not empty.
  111. function validatePassword(value){
  112. if(value){
  113. loginPasswordError.style.opacity = 0
  114. lp = true
  115. if(lu){
  116. loginDisabled(false)
  117. }
  118. } else {
  119. lp = false
  120. showError(loginPasswordError, '* Required')
  121. loginDisabled(true)
  122. }
  123. }
  124. // Emphasize errors with shake when focus is lost.
  125. loginUsername.addEventListener('focusout', (e) => {
  126. validateEmail(e.target.value)
  127. shakeError(loginEmailError)
  128. })
  129. loginPassword.addEventListener('focusout', (e) => {
  130. validatePassword(e.target.value)
  131. shakeError(loginPasswordError)
  132. })
  133. // Validate input for each field.
  134. loginUsername.addEventListener('input', (e) => {
  135. validateEmail(e.target.value)
  136. })
  137. loginPassword.addEventListener('input', (e) => {
  138. validatePassword(e.target.value)
  139. })
  140. // Enable or disable login button.
  141. function loginDisabled(v){
  142. if(loginButton.disabled !== v){
  143. loginButton.disabled = v
  144. }
  145. }
  146. // Enable or disable loading elements.
  147. function loginLoading(v){
  148. if(v){
  149. loginButton.setAttribute('loading', v)
  150. loginButton.innerHTML = loginButton.innerHTML.replace('LOGIN', 'LOGGING IN')
  151. } else {
  152. loginButton.removeAttribute('loading')
  153. loginButton.innerHTML = loginButton.innerHTML.replace('LOGGING IN', 'LOGIN')
  154. }
  155. }
  156. // Disable or enable login form.
  157. function formDisabled(v){
  158. loginDisabled(v)
  159. loginUsername.disabled = v
  160. loginPassword.disabled = v
  161. if(v){
  162. checkmarkContainer.setAttribute('disabled', v)
  163. } else {
  164. checkmarkContainer.removeAttribute('disabled')
  165. }
  166. loginRememberOption.disabled = v
  167. }
  168. function resolveError(err){
  169. // Mojang Response => err.cause | err.error | err.errorMessage
  170. // Node error => err.code | err.message
  171. if(err.cause != null && err.cause === 'UserMigratedException') {
  172. return {
  173. title: 'Error During Login:<br>Invalid Credentials',
  174. desc: 'You\'ve attempted to login with a migrated account. Try again using the account email as the username.'
  175. }
  176. } else {
  177. if(err.error != null){
  178. if(err.error === 'ForbiddenOperationException'){
  179. if(err.errorMessage != null){
  180. if(err.errorMessage === 'Invalid credentials. Invalid username or password.'){
  181. return {
  182. title: 'Error During Login:<br>Invalid Credentials',
  183. desc: 'The email or password you\'ve entered is incorrect. Please try again.'
  184. }
  185. } else if(err.errorMessage === 'Invalid credentials.'){
  186. return {
  187. title: 'Error During Login:<br>Too Many Attempts',
  188. desc: 'There have been too many login attempts with this account recently. Please try again later.'
  189. }
  190. }
  191. }
  192. }
  193. } else {
  194. // Request errors (from Node).
  195. if(err.code != null){
  196. if(err.code === 'ENOENT'){
  197. // No Internet.
  198. return {
  199. title: 'Error During Login:<br>No Internet Connection',
  200. desc: 'You must be connected to the internet in order to login. Please connect and try again.'
  201. }
  202. } else if(err.code === 'ENOTFOUND'){
  203. // Could not reach server.
  204. return {
  205. title: 'Error During Login:<br>Authentication Server Offline',
  206. desc: 'Mojang\'s authentication server is currently offline or unreachable. Please wait a bit and try again. You can check the status of the server on <a href="https://help.mojang.com/">Mojang\'s help portal</a>.'
  207. }
  208. }
  209. }
  210. }
  211. }
  212. if(err.message != null){
  213. // Unknown error with request.
  214. return {
  215. title: 'Error During Login:<br>Unknown Error',
  216. desc: err.message
  217. }
  218. } else {
  219. // Unknown Mojang error.
  220. return {
  221. title: err.error,
  222. desc: err.errorMessage
  223. }
  224. }
  225. }
  226. loginButton.addEventListener('click', () => {
  227. // Disable form.
  228. formDisabled(true)
  229. // Show loading stuff.
  230. loginLoading(true)
  231. AuthManager.addAccount(loginUsername.value, loginPassword.value).then((value) => {
  232. loginButton.innerHTML = loginButton.innerHTML.replace('LOGGING IN', 'SUCCESS')
  233. $('.circle-loader').toggleClass('load-complete')
  234. $('.checkmark').toggle()
  235. //console.log(value)
  236. setTimeout(() => {
  237. $('#loginContainer').fadeOut(500, () => {
  238. $('#landingContainer').fadeIn(500)
  239. })
  240. }, 1000)
  241. }).catch((err) => {
  242. loginLoading(false)
  243. const errF = resolveError(err)
  244. setOverlayContent(errF.title, errF.desc, 'Try Again')
  245. setOverlayHandler(() => {
  246. formDisabled(false)
  247. toggleOverlay(false)
  248. })
  249. toggleOverlay(true)
  250. console.log(err)
  251. })
  252. })
  253. </script>
  254. <!-- Will reuse this down the line, then it will be removed from this file. -->
  255. <!--<div id="loginLoading">
  256. <div id="loginLoadingContent">
  257. <div id="loadSpinnerContainer">
  258. <img id="loadCenterImage" src="assets/images/westeroscraftlogo1.png">
  259. <img id="loadSpinnerImage" class="rotating" src="assets/images/westeroscraftlogo2.png">
  260. </div>
  261. <span id="loadDescText">LOGGING IN</span>
  262. </div>
  263. </div>-->
  264. </div>