PersonalContainer.js 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. import { Container } from 'unstated';
  2. import { AttachmentType } from '~/server/interfaces/attachment';
  3. import loggerFactory from '~/utils/logger';
  4. import { apiPost } from '../util/apiv1-client';
  5. import { apiv3Get, apiv3Put } from '../util/apiv3-client';
  6. // eslint-disable-next-line no-unused-vars
  7. const logger = loggerFactory('growi:services:PersonalContainer');
  8. const DEFAULT_IMAGE = '/images/icons/user.svg';
  9. /**
  10. * Service container for personal settings page (PersonalSettings.jsx)
  11. * @extends {Container} unstated Container
  12. */
  13. export default class PersonalContainer extends Container {
  14. constructor(appContainer) {
  15. super();
  16. this.appContainer = appContainer;
  17. this.state = {
  18. retrieveError: null,
  19. name: '',
  20. email: '',
  21. registrationWhiteList: this.appContainer.getConfig().registrationWhiteList,
  22. isEmailPublished: false,
  23. lang: 'en_US',
  24. isGravatarEnabled: false,
  25. isUploadedPicture: false,
  26. uploadedPictureSrc: this.getUploadedPictureSrc(this.appContainer.currentUser),
  27. externalAccounts: [],
  28. apiToken: '',
  29. slackMemberId: '',
  30. };
  31. }
  32. /**
  33. * Workaround for the mangling in production build to break constructor.name
  34. */
  35. static getClassName() {
  36. return 'PersonalContainer';
  37. }
  38. /**
  39. * retrieve personal data
  40. */
  41. async retrievePersonalData() {
  42. try {
  43. const response = await apiv3Get('/personal-setting/');
  44. const { currentUser } = response.data;
  45. this.setState({
  46. name: currentUser.name,
  47. email: currentUser.email,
  48. isEmailPublished: currentUser.isEmailPublished,
  49. lang: currentUser.lang,
  50. isGravatarEnabled: currentUser.isGravatarEnabled,
  51. apiToken: currentUser.apiToken,
  52. slackMemberId: currentUser.slackMemberId,
  53. });
  54. }
  55. catch (err) {
  56. this.setState({ retrieveError: err });
  57. logger.error(err);
  58. throw new Error('Failed to fetch personal data');
  59. }
  60. }
  61. /**
  62. * define a function for uploaded picture
  63. */
  64. getUploadedPictureSrc(user) {
  65. if (user == null) {
  66. return DEFAULT_IMAGE;
  67. }
  68. if (user.image) {
  69. this.setState({ isUploadedPicture: true });
  70. return user.image;
  71. }
  72. if (user.imageAttachment != null) {
  73. this.setState({ isUploadedPicture: true });
  74. return user.imageAttachment.filePathProxied;
  75. }
  76. return DEFAULT_IMAGE;
  77. }
  78. /**
  79. * retrieve external accounts that linked me
  80. */
  81. async retrieveExternalAccounts() {
  82. try {
  83. const response = await apiv3Get('/personal-setting/external-accounts');
  84. const { externalAccounts } = response.data;
  85. this.setState({ externalAccounts });
  86. }
  87. catch (err) {
  88. this.setState({ retrieveError: err });
  89. logger.error(err);
  90. throw new Error('Failed to fetch external accounts');
  91. }
  92. }
  93. /**
  94. * Change name
  95. */
  96. changeName(inputValue) {
  97. this.setState({ name: inputValue });
  98. }
  99. /**
  100. * Change email
  101. */
  102. changeEmail(inputValue) {
  103. this.setState({ email: inputValue });
  104. }
  105. /**
  106. * Change Slack Member ID
  107. */
  108. changeSlackMemberId(inputValue) {
  109. this.setState({ slackMemberId: inputValue });
  110. }
  111. /**
  112. * Change isEmailPublished
  113. */
  114. changeIsEmailPublished(boolean) {
  115. this.setState({ isEmailPublished: boolean });
  116. }
  117. /**
  118. * Change lang
  119. */
  120. changeLang(lang) {
  121. this.setState({ lang });
  122. }
  123. /**
  124. * Change isGravatarEnabled
  125. */
  126. changeIsGravatarEnabled(boolean) {
  127. this.setState({ isGravatarEnabled: boolean });
  128. }
  129. /**
  130. * Update basic info
  131. * @memberOf PersonalContainer
  132. * @return {Array} basic info
  133. */
  134. async updateBasicInfo() {
  135. try {
  136. const response = await apiv3Put('/personal-setting/', {
  137. name: this.state.name,
  138. email: this.state.email,
  139. isEmailPublished: this.state.isEmailPublished,
  140. lang: this.state.lang,
  141. slackMemberId: this.state.slackMemberId,
  142. });
  143. const { updatedUser } = response.data;
  144. this.setState({
  145. name: updatedUser.name,
  146. email: updatedUser.email,
  147. isEmailPublished: updatedUser.isEmailPublished,
  148. lang: updatedUser.lang,
  149. slackMemberId: updatedUser.slackMemberId,
  150. });
  151. }
  152. catch (err) {
  153. this.setState({ retrieveError: err });
  154. logger.error(err);
  155. throw new Error('Failed to update personal data');
  156. }
  157. }
  158. /**
  159. * Update profile image
  160. * @memberOf PersonalContainer
  161. */
  162. async updateProfileImage() {
  163. try {
  164. const response = await apiv3Put('/personal-setting/image-type', {
  165. isGravatarEnabled: this.state.isGravatarEnabled,
  166. });
  167. const { userData } = response.data;
  168. this.setState({
  169. isGravatarEnabled: userData.isGravatarEnabled,
  170. });
  171. }
  172. catch (err) {
  173. this.setState({ retrieveError: err });
  174. logger.error(err);
  175. throw new Error('Failed to update profile image');
  176. }
  177. }
  178. /**
  179. * Upload image
  180. */
  181. async uploadAttachment(file) {
  182. try {
  183. const formData = new FormData();
  184. formData.append('file', file);
  185. formData.append('_csrf', this.appContainer.csrfToken);
  186. formData.append('attachmentType', AttachmentType.PROFILE_IMAGE);
  187. const response = await apiPost('/attachments.uploadProfileImage', formData);
  188. this.setState({ isUploadedPicture: true, uploadedPictureSrc: response.attachment.filePathProxied });
  189. }
  190. catch (err) {
  191. this.setState({ retrieveError: err });
  192. logger.error(err);
  193. throw new Error('Failed to upload profile image');
  194. }
  195. }
  196. /**
  197. * Delete image
  198. */
  199. async deleteProfileImage() {
  200. try {
  201. await apiPost('/attachments.removeProfileImage', { _csrf: this.appContainer.csrfToken });
  202. this.setState({ isUploadedPicture: false, uploadedPictureSrc: DEFAULT_IMAGE });
  203. }
  204. catch (err) {
  205. this.setState({ retrieveError: err });
  206. logger.error(err);
  207. throw new Error('Failed to delete profile image');
  208. }
  209. }
  210. /**
  211. * Associate LDAP account
  212. */
  213. async associateLdapAccount(account) {
  214. try {
  215. await apiv3Put('/personal-setting/associate-ldap', account);
  216. }
  217. catch (err) {
  218. this.setState({ retrieveError: err });
  219. logger.error(err);
  220. throw new Error('Failed to associate ldap account');
  221. }
  222. }
  223. /**
  224. * Disassociate LDAP account
  225. */
  226. async disassociateLdapAccount(account) {
  227. try {
  228. await apiv3Put('/personal-setting/disassociate-ldap', account);
  229. }
  230. catch (err) {
  231. this.setState({ retrieveError: err });
  232. logger.error(err);
  233. throw new Error('Failed to disassociate ldap account');
  234. }
  235. }
  236. }