UserAffiliationsController.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. import _ from 'lodash'
  2. /* eslint-disable
  3. max-len,
  4. no-return-assign,
  5. no-useless-escape,
  6. */
  7. import App from '../../../base'
  8. export default App.controller('UserAffiliationsController', function(
  9. $scope,
  10. $rootScope,
  11. UserAffiliationsDataService,
  12. $q,
  13. $window
  14. ) {
  15. $scope.userEmails = []
  16. $scope.linkedInstitutionIds = []
  17. $scope.hideInstitutionNotifications = {}
  18. $scope.closeInstitutionNotification = type => {
  19. $scope.hideInstitutionNotifications[type] = true
  20. }
  21. $scope.samlBetaSession = ExposedSettings.hasSamlBeta
  22. $scope.samlInitPath = ExposedSettings.samlInitPath
  23. $scope.reconfirmationRemoveEmail = $window.data.reconfirmationRemoveEmail
  24. $scope.reconfirmedViaSAML = $window.data.reconfirmedViaSAML
  25. const LOCAL_AND_DOMAIN_REGEX = /([^@]+)@(.+)/
  26. const EMAIL_REGEX = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\ ".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA -Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
  27. const _matchLocalAndDomain = function(userEmailInput) {
  28. const match = userEmailInput
  29. ? userEmailInput.match(LOCAL_AND_DOMAIN_REGEX)
  30. : undefined
  31. if (match) {
  32. return { local: match[1], domain: match[2] }
  33. } else {
  34. return { local: null, domain: null }
  35. }
  36. }
  37. const _ssoAvailableForAffiliation = affiliation => {
  38. if (!affiliation) return false
  39. const institution = affiliation.institution
  40. if (!_ssoAvailableForInstitution(institution)) return false
  41. if (!institution.confirmed) return false // domain is confirmed, not the email
  42. return true
  43. }
  44. const _ssoAvailableForDomain = domain => {
  45. if (!domain) return false
  46. if (!domain.confirmed) return false // domain is confirmed, not the email
  47. const institution = domain.university
  48. if (!_ssoAvailableForInstitution(institution)) return false
  49. return true
  50. }
  51. const _ssoAvailableForInstitution = institution => {
  52. if (!ExposedSettings.hasSamlFeature) return false
  53. if (!institution) return false
  54. if (institution.ssoEnabled) return true
  55. if ($scope.samlBetaSession && institution.ssoBeta) return true
  56. return false
  57. }
  58. $scope.getEmailSuggestion = function(userInput) {
  59. const userInputLocalAndDomain = _matchLocalAndDomain(userInput)
  60. $scope.ui.isValidEmail = EMAIL_REGEX.test(userInput)
  61. $scope.ui.isBlacklistedEmail = false
  62. $scope.ui.showManualUniversitySelectionUI = false
  63. if (userInputLocalAndDomain.domain) {
  64. $scope.ui.isBlacklistedEmail = UserAffiliationsDataService.isDomainBlacklisted(
  65. userInputLocalAndDomain.domain
  66. )
  67. return UserAffiliationsDataService.getUniversityDomainFromPartialDomainInput(
  68. userInputLocalAndDomain.domain
  69. )
  70. .then(function(universityDomain) {
  71. const currentUserInputLocalAndDomain = _matchLocalAndDomain(
  72. $scope.newAffiliation.email
  73. )
  74. if (
  75. currentUserInputLocalAndDomain.domain === universityDomain.hostname
  76. ) {
  77. $scope.newAffiliation.university = universityDomain.university
  78. $scope.newAffiliation.department = universityDomain.department
  79. $scope.newAffiliation.ssoAvailable = _ssoAvailableForDomain(
  80. universityDomain
  81. )
  82. } else {
  83. _resetAffiliationSuggestion()
  84. }
  85. return $q.resolve(
  86. `${userInputLocalAndDomain.local}@${universityDomain.hostname}`
  87. )
  88. })
  89. .catch(function() {
  90. _resetAffiliationSuggestion()
  91. return $q.reject(null)
  92. })
  93. } else {
  94. _resetAffiliationSuggestion()
  95. return $q.reject(null)
  96. }
  97. }
  98. $scope.linkInstitutionAcct = function(email, institutionId) {
  99. _resetMakingRequestType()
  100. $scope.ui.isMakingRequest = true
  101. $scope.ui.isProcessing = true
  102. $window.location.href = `${$scope.samlInitPath}?university_id=${institutionId}&auto=/user/settings&email=${email}`
  103. }
  104. $scope.selectUniversityManually = function() {
  105. _resetAffiliationSuggestion()
  106. $scope.ui.showManualUniversitySelectionUI = true
  107. }
  108. $scope.changeAffiliation = function(userEmail) {
  109. if (_.get(userEmail, ['affiliation', 'institution', 'id'])) {
  110. UserAffiliationsDataService.getUniversityDetails(
  111. userEmail.affiliation.institution.id
  112. ).then(
  113. universityDetails =>
  114. ($scope.affiliationToChange.university = universityDetails)
  115. )
  116. }
  117. $scope.affiliationToChange.email = userEmail.email
  118. $scope.affiliationToChange.role = userEmail.affiliation.role
  119. $scope.affiliationToChange.department = userEmail.affiliation.department
  120. }
  121. $scope.saveAffiliationChange = function(userEmail) {
  122. userEmail.affiliation.role = $scope.affiliationToChange.role
  123. userEmail.affiliation.department = $scope.affiliationToChange.department
  124. _resetAffiliationToChange()
  125. return _monitorRequest(
  126. UserAffiliationsDataService.addRoleAndDepartment(
  127. userEmail.email,
  128. userEmail.affiliation.role,
  129. userEmail.affiliation.department
  130. )
  131. ).then(() => setTimeout(() => _getUserEmails()))
  132. }
  133. $scope.cancelAffiliationChange = email => _resetAffiliationToChange()
  134. $scope.isChangingAffiliation = email =>
  135. $scope.affiliationToChange.email === email
  136. $scope.showAddEmailForm = () => ($scope.ui.showAddEmailUI = true)
  137. $scope.addNewEmail = function() {
  138. let addEmailPromise
  139. if (!$scope.newAffiliation.university) {
  140. addEmailPromise = UserAffiliationsDataService.addUserEmail(
  141. $scope.newAffiliation.email
  142. )
  143. } else {
  144. if ($scope.newAffiliation.university.isUserSuggested) {
  145. addEmailPromise = UserAffiliationsDataService.addUserAffiliationWithUnknownUniversity(
  146. $scope.newAffiliation.email,
  147. $scope.newAffiliation.university.name,
  148. $scope.newAffiliation.country.code,
  149. $scope.newAffiliation.role,
  150. $scope.newAffiliation.department
  151. )
  152. } else {
  153. addEmailPromise = UserAffiliationsDataService.addUserAffiliation(
  154. $scope.newAffiliation.email,
  155. $scope.newAffiliation.university.id,
  156. $scope.newAffiliation.role,
  157. $scope.newAffiliation.department
  158. )
  159. }
  160. }
  161. $scope.ui.isAddingNewEmail = true
  162. $scope.ui.showAddEmailUI = false
  163. return _monitorRequest(addEmailPromise)
  164. .then(function() {
  165. _resetNewAffiliation()
  166. _resetAddingEmail()
  167. setTimeout(() => _getUserEmails())
  168. })
  169. .finally(() => ($scope.ui.isAddingNewEmail = false))
  170. }
  171. $scope.setDefaultUserEmail = userEmail =>
  172. _monitorRequest(
  173. UserAffiliationsDataService.setDefaultUserEmail(userEmail.email)
  174. ).then(function() {
  175. for (let email of $scope.userEmails || []) {
  176. email.default = false
  177. }
  178. userEmail.default = true
  179. window.usersEmail = userEmail.email
  180. $rootScope.usersEmail = userEmail.email
  181. })
  182. $scope.removeUserEmail = function(userEmail) {
  183. $scope.userEmails = $scope.userEmails.filter(ue => ue !== userEmail)
  184. return _monitorRequest(
  185. UserAffiliationsDataService.removeUserEmail(userEmail.email)
  186. )
  187. }
  188. $scope.resendConfirmationEmail = function(userEmail) {
  189. _resetMakingRequestType()
  190. $scope.ui.isResendingConfirmation = true
  191. return _monitorRequest(
  192. UserAffiliationsDataService.resendConfirmationEmail(userEmail.email)
  193. ).finally(() => ($scope.ui.isResendingConfirmation = false))
  194. }
  195. $scope.acknowledgeError = function() {
  196. _reset()
  197. return _getUserEmails()
  198. }
  199. var _resetAffiliationToChange = () =>
  200. ($scope.affiliationToChange = {
  201. email: '',
  202. university: null,
  203. role: null,
  204. department: null
  205. })
  206. var _resetNewAffiliation = () =>
  207. ($scope.newAffiliation = {
  208. email: '',
  209. country: null,
  210. university: null,
  211. role: null,
  212. department: null
  213. })
  214. var _resetAddingEmail = function() {
  215. $scope.ui.showAddEmailUI = false
  216. $scope.ui.isValidEmail = false
  217. $scope.ui.isBlacklistedEmail = false
  218. $scope.ui.showManualUniversitySelectionUI = false
  219. }
  220. var _resetAffiliationSuggestion = () => {
  221. $scope.newAffiliation = {
  222. email: $scope.newAffiliation.email
  223. }
  224. }
  225. var _resetMakingRequestType = function() {
  226. $scope.ui.isLoadingEmails = false
  227. $scope.ui.isProcessing = false
  228. $scope.ui.isResendingConfirmation = false
  229. }
  230. var _reset = function() {
  231. $scope.ui = {
  232. hasError: false,
  233. errorMessage: '',
  234. showChangeAffiliationUI: false,
  235. isMakingRequest: false,
  236. isLoadingEmails: false,
  237. isAddingNewEmail: false
  238. }
  239. _resetAffiliationToChange()
  240. _resetNewAffiliation()
  241. return _resetAddingEmail()
  242. }
  243. _reset()
  244. var _monitorRequest = function(promise) {
  245. $scope.ui.hasError = false
  246. $scope.ui.isMakingRequest = true
  247. promise
  248. .catch(function(response) {
  249. $scope.ui.hasError = true
  250. $scope.ui.errorMessage = _.get(response, ['data', 'message'])
  251. })
  252. .finally(() => ($scope.ui.isMakingRequest = false))
  253. return promise
  254. }
  255. $scope.inReconfirmNotificationPeriod = function(emailData) {
  256. return _.get(emailData, ['affiliation', 'inReconfirmNotificationPeriod'])
  257. }
  258. $scope.institutionAlreadyLinked = function(emailData) {
  259. const institutionId =
  260. emailData.affiliation &&
  261. emailData.affiliation.institution &&
  262. emailData.affiliation.institution &&
  263. emailData.affiliation.institution.id
  264. ? emailData.affiliation.institution.id.toString()
  265. : undefined
  266. return $scope.linkedInstitutionIds.indexOf(institutionId) !== -1
  267. }
  268. // Populates the emails table
  269. var _getUserEmails = function() {
  270. _resetMakingRequestType()
  271. $scope.ui.isLoadingEmails = true
  272. _monitorRequest(
  273. UserAffiliationsDataService.getUserEmailsEnsureAffiliation()
  274. )
  275. .then(emails => {
  276. $scope.userEmails = emails.map(email => {
  277. email.ssoAvailable = _ssoAvailableForAffiliation(email.affiliation)
  278. return email
  279. })
  280. $scope.linkedInstitutionIds = emails
  281. .filter(email => {
  282. if (email.samlProviderId) {
  283. return email.samlProviderId
  284. }
  285. })
  286. .map(email => email.samlProviderId)
  287. })
  288. .finally(() => ($scope.ui.isLoadingEmails = false))
  289. }
  290. _getUserEmails()
  291. })