| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328 | import { ReactiveCache } from '/imports/reactiveCache';import LockoutSettings from '/models/lockoutSettings';const orgsPerPage = 25;const teamsPerPage = 25;const usersPerPage = 25;let userOrgsTeamsAction = ""; //poosible actions 'addOrg', 'addTeam', 'removeOrg' or 'removeTeam' when adding or modifying a userlet selectedUserChkBoxUserIds = [];BlazeComponent.extendComponent({  mixins() {    return [Mixins.InfiniteScrolling];  },  onCreated() {    this.error = new ReactiveVar('');    this.loading = new ReactiveVar(false);    this.orgSetting = new ReactiveVar(true);    this.teamSetting = new ReactiveVar(false);    this.peopleSetting = new ReactiveVar(false);    this.lockedUsersSetting = new ReactiveVar(false);    this.findOrgsOptions = new ReactiveVar({});    this.findTeamsOptions = new ReactiveVar({});    this.findUsersOptions = new ReactiveVar({});    this.numberOrgs = new ReactiveVar(0);    this.numberTeams = new ReactiveVar(0);    this.numberPeople = new ReactiveVar(0);    this.userFilterType = new ReactiveVar('all');    this.page = new ReactiveVar(1);    this.loadNextPageLocked = false;    this.callFirstWith(null, 'resetNextPeak');    this.autorun(() => {      const limitOrgs = this.page.get() * orgsPerPage;      const limitTeams = this.page.get() * teamsPerPage;      const limitUsers = this.page.get() * usersPerPage;      this.subscribe('org', this.findOrgsOptions.get(), limitOrgs, () => {        this.loadNextPageLocked = false;        const nextPeakBefore = this.callFirstWith(null, 'getNextPeak');        this.calculateNextPeak();        const nextPeakAfter = this.callFirstWith(null, 'getNextPeak');        if (nextPeakBefore === nextPeakAfter) {          this.callFirstWith(null, 'resetNextPeak');        }      });      this.subscribe('team', this.findTeamsOptions.get(), limitTeams, () => {        this.loadNextPageLocked = false;        const nextPeakBefore = this.callFirstWith(null, 'getNextPeak');        this.calculateNextPeak();        const nextPeakAfter = this.callFirstWith(null, 'getNextPeak');        if (nextPeakBefore === nextPeakAfter) {          this.callFirstWith(null, 'resetNextPeak');        }      });      this.subscribe('people', this.findUsersOptions.get(), limitUsers, () => {        this.loadNextPageLocked = false;        const nextPeakBefore = this.callFirstWith(null, 'getNextPeak');        this.calculateNextPeak();        const nextPeakAfter = this.callFirstWith(null, 'getNextPeak');        if (nextPeakBefore === nextPeakAfter) {          this.callFirstWith(null, 'resetNextPeak');        }      });    });  },  events() {    return [      {        'click #searchOrgButton'() {          this.filterOrg();        },        'keydown #searchOrgInput'(event) {          if (event.keyCode === 13 && !event.shiftKey) {            this.filterOrg();          }        },        'click #searchTeamButton'() {          this.filterTeam();        },        'keydown #searchTeamInput'(event) {          if (event.keyCode === 13 && !event.shiftKey) {            this.filterTeam();          }        },        'click #searchButton'() {          this.filterPeople();        },        'click #addOrRemoveTeam'(){          document.getElementById("divAddOrRemoveTeamContainer").style.display = 'block';        },        'keydown #searchInput'(event) {          if (event.keyCode === 13 && !event.shiftKey) {            this.filterPeople();          }        },        'change #userFilterSelect'(event) {          const filterType = $(event.target).val();          this.userFilterType.set(filterType);          this.filterPeople();        },        'click #unlockAllUsers'(event) {          event.preventDefault();          if (confirm(TAPi18n.__('accounts-lockout-confirm-unlock-all'))) {            Meteor.call('unlockAllUsers', (error) => {              if (error) {                console.error('Error unlocking all users:', error);              } else {                // Show a brief success message                const message = document.createElement('div');                message.className = 'unlock-all-success';                message.textContent = TAPi18n.__('accounts-lockout-all-users-unlocked');                document.body.appendChild(message);                // Remove the message after a short delay                setTimeout(() => {                  if (message.parentNode) {                    message.parentNode.removeChild(message);                  }                }, 3000);              }            });          }        },        'click #newOrgButton'() {          Popup.open('newOrg');        },        'click #newTeamButton'() {          Popup.open('newTeam');        },        'click #newUserButton'() {          Popup.open('newUser');        },        'click a.js-org-menu': this.switchMenu,        'click a.js-team-menu': this.switchMenu,        'click a.js-people-menu': this.switchMenu,        'click a.js-locked-users-menu': this.switchMenu,      },    ];  },  filterPeople() {    const value = $('#searchInput').first().val();    const filterType = this.userFilterType.get();    const currentTime = Number(new Date());    let query = {};    // Apply text search filter if there's a search value    if (value !== '') {      const regex = new RegExp(value, 'i');      query = {        $or: [          { username: regex },          { 'profile.fullname': regex },          { 'emails.address': regex },        ],      };    }    // Apply filter based on selected option    switch (filterType) {      case 'locked':        // Show only locked users        query['services.accounts-lockout.unlockTime'] = { $gt: currentTime };        break;      case 'active':        // Show only active users (loginDisabled is false or undefined)        query['loginDisabled'] = { $ne: true };        break;      case 'inactive':        // Show only inactive users (loginDisabled is true)        query['loginDisabled'] = true;        break;      case 'all':      default:        // Show all users, no additional filter        break;    }    this.findUsersOptions.set(query);  },  loadNextPage() {    if (this.loadNextPageLocked === false) {      this.page.set(this.page.get() + 1);      this.loadNextPageLocked = true;    }  },  calculateNextPeak() {    const element = this.find('.main-body');    if (element) {      const altitude = element.scrollHeight;      this.callFirstWith(this, 'setNextPeak', altitude);    }  },  reachNextPeak() {    this.loadNextPage();  },  setError(error) {    this.error.set(error);  },  setLoading(w) {    this.loading.set(w);  },  orgList() {    const limitOrgs = this.page.get() * orgsPerPage;    const orgs = ReactiveCache.getOrgs(this.findOrgsOptions.get(), {      sort: { orgDisplayName: 1 },      limit: limitOrgs,      fields: { _id: true },    });    // Count only the items currently loaded to browser, not total from database    this.numberOrgs.set(orgs.length);    return orgs;  },  teamList() {    const limitTeams = this.page.get() * teamsPerPage;    const teams = ReactiveCache.getTeams(this.findTeamsOptions.get(), {      sort: { teamDisplayName: 1 },      limit: limitTeams,      fields: { _id: true },    });    // Count only the items currently loaded to browser, not total from database    this.numberTeams.set(teams.length);    return teams;  },  peopleList() {    const limitUsers = this.page.get() * usersPerPage;    const users = ReactiveCache.getUsers(this.findUsersOptions.get(), {      sort: { username: 1 },      limit: limitUsers,      fields: { _id: true },    });    // Count only the items currently loaded to browser, not total from database    this.numberPeople.set(users.length);    return users;  },  orgNumber() {    return this.numberOrgs.get();  },  teamNumber() {    return this.numberTeams.get();  },  peopleNumber() {    return this.numberPeople.get();  },  switchMenu(event) {    const target = $(event.target);    if (!target.hasClass('active')) {      $('.side-menu li.active').removeClass('active');      target.parent().addClass('active');      const targetID = target.data('id');      this.orgSetting.set('org-setting' === targetID);      this.teamSetting.set('team-setting' === targetID);      this.peopleSetting.set('people-setting' === targetID);      this.lockedUsersSetting.set('locked-users-setting' === targetID);      // When switching to locked users tab, refresh the locked users list      if ('locked-users-setting' === targetID) {        // Find the lockedUsersGeneral component and call refreshLockedUsers        const lockedUsersComponent = Blaze.getView($('.main-body')[0])._templateInstance;        if (lockedUsersComponent && lockedUsersComponent.refreshLockedUsers) {          lockedUsersComponent.refreshLockedUsers();        }      }    }  },}).register('people');Template.orgRow.helpers({  orgData() {    return ReactiveCache.getOrg(this.orgId);  },});Template.teamRow.helpers({  teamData() {    return ReactiveCache.getTeam(this.teamId);  },});Template.peopleRow.helpers({  userData() {    return ReactiveCache.getUser(this.userId);  },  isUserLocked() {    const user = ReactiveCache.getUser(this.userId);    if (!user) return false;    // Check if user has accounts-lockout with unlockTime property    if (user.services &&        user.services['accounts-lockout'] &&        user.services['accounts-lockout'].unlockTime) {      // Check if unlockTime is in the future      const currentTime = Number(new Date());      return user.services['accounts-lockout'].unlockTime > currentTime;    }    return false;  }});// Initialize filter dropdownTemplate.people.rendered = function() {  const template = this;  // Set the initial value of the dropdown  Tracker.afterFlush(function() {    if (template.findAll('#userFilterSelect').length) {      $('#userFilterSelect').val('all');    }  });};Template.editUserPopup.onCreated(function () {  this.authenticationMethods = new ReactiveVar([]);  this.errorMessage = new ReactiveVar('');  Meteor.call('getAuthenticationsEnabled', (_, result) => {    if (result) {      // TODO : add a management of different languages      // (ex {value: ldap, text: TAPi18n.__('ldap', {}, T9n.getLanguage() || 'en')})      this.authenticationMethods.set([        { value: 'password' },        // Gets only the authentication methods availables        ...Object.entries(result)          .filter((e) => e[1])          .map((e) => ({ value: e[0] })),      ]);    }  });});Template.editOrgPopup.helpers({  org() {    return ReactiveCache.getOrg(this.orgId);  },  errorMessage() {    return Template.instance().errorMessage.get();  },});Template.editTeamPopup.helpers({  team() {    return ReactiveCache.getTeam(this.teamId);  },  errorMessage() {    return Template.instance().errorMessage.get();  },});Template.editUserPopup.helpers({  user() {    return ReactiveCache.getUser(this.userId);  },  authentications() {    return Template.instance().authenticationMethods.get();  },  orgsDatas() {    const ret = ReactiveCache.getOrgs({}, {sort: { orgDisplayName: 1 }});    return ret;  },  teamsDatas() {    const ret = ReactiveCache.getTeams({}, {sort: { teamDisplayName: 1 }});    return ret;  },  isSelected(match) {    const userId = Template.instance().data.userId;    const selected = ReactiveCache.getUser(userId).authenticationMethod;    return selected === match;  },  isLdap() {    const userId = Template.instance().data.userId;    const selected = ReactiveCache.getUser(userId).authenticationMethod;    return selected === 'ldap';  },  errorMessage() {    return Template.instance().errorMessage.get();  },});Template.newOrgPopup.onCreated(function () {  this.errorMessage = new ReactiveVar('');});Template.newTeamPopup.onCreated(function () {  this.errorMessage = new ReactiveVar('');});Template.newUserPopup.onCreated(function () {  this.authenticationMethods = new ReactiveVar([]);  this.errorMessage = new ReactiveVar('');  Meteor.call('getAuthenticationsEnabled', (_, result) => {    if (result) {      // TODO : add a management of different languages      // (ex {value: ldap, text: TAPi18n.__('ldap', {}, T9n.getLanguage() || 'en')})      this.authenticationMethods.set([        { value: 'password' },        // Gets only the authentication methods availables        ...Object.entries(result)          .filter((e) => e[1])          .map((e) => ({ value: e[0] })),      ]);    }  });});Template.newOrgPopup.helpers({  org() {    return ReactiveCache.getOrg(this.orgId);  },  errorMessage() {    return Template.instance().errorMessage.get();  },});Template.newTeamPopup.helpers({  team() {    return ReactiveCache.getTeam(this.teamId);  },  errorMessage() {    return Template.instance().errorMessage.get();  },});Template.newUserPopup.helpers({  user() {    return ReactiveCache.getUser(this.userId);  },  authentications() {    return Template.instance().authenticationMethods.get();  },  orgsDatas() {    const ret = ReactiveCache.getOrgs({}, {sort: { orgDisplayName: 1 }});    return ret;  },  teamsDatas() {    const ret = ReactiveCache.getTeams({}, {sort: { teamDisplayName: 1 }});    return ret;  },  isSelected(match) {    const userId = Template.instance().data.userId;    if(userId){      const selected = ReactiveCache.getUser(userId).authenticationMethod;      return selected === match;    }    else{      false;    }  },  isLdap() {    const userId = Template.instance().data.userId;    const selected = ReactiveCache.getUser(userId).authenticationMethod;    return selected === 'ldap';  },  errorMessage() {    return Template.instance().errorMessage.get();  },});BlazeComponent.extendComponent({  onCreated() {},  org() {    return ReactiveCache.getOrg(this.orgId);  },  events() {    return [      {        'click a.edit-org': Popup.open('editOrg'),        'click a.more-settings-org': Popup.open('settingsOrg'),      },    ];  },}).register('orgRow');BlazeComponent.extendComponent({  onCreated() {},  team() {    return ReactiveCache.getTeam(this.teamId);  },  events() {    return [      {        'click a.edit-team': Popup.open('editTeam'),        'click a.more-settings-team': Popup.open('settingsTeam'),      },    ];  },}).register('teamRow');BlazeComponent.extendComponent({  onCreated() {},  user() {    return ReactiveCache.getUser(this.userId);  },  events() {    return [      {        'click a.edit-user': Popup.open('editUser'),        'click a.more-settings-user': Popup.open('settingsUser'),        'click .selectUserChkBox': function(ev){            if(ev.currentTarget){              if(ev.currentTarget.checked){                if(!selectedUserChkBoxUserIds.includes(ev.currentTarget.id)){                  selectedUserChkBoxUserIds.push(ev.currentTarget.id);                }              }              else{                if(selectedUserChkBoxUserIds.includes(ev.currentTarget.id)){                  let index = selectedUserChkBoxUserIds.indexOf(ev.currentTarget.id);                  if(index > -1)                    selectedUserChkBoxUserIds.splice(index, 1);                }              }            }            if(selectedUserChkBoxUserIds.length > 0)              document.getElementById("divAddOrRemoveTeam").style.display = 'block';            else              document.getElementById("divAddOrRemoveTeam").style.display = 'none';        },        'click .js-toggle-active-status': function(ev) {            ev.preventDefault();            const userId = this.userId;            const user = ReactiveCache.getUser(userId);            if (!user) return;            // Toggle loginDisabled status            const isActive = !(user.loginDisabled === true);            // Update the user's active status            Users.update(userId, {              $set: {                loginDisabled: isActive              }            });        },        'click .js-toggle-lock-status': function(ev){            ev.preventDefault();            const userId = this.userId;            const user = ReactiveCache.getUser(userId);            if (!user) return;            // Check if user is currently locked            const isLocked = user.services &&                user.services['accounts-lockout'] &&                user.services['accounts-lockout'].unlockTime &&                user.services['accounts-lockout'].unlockTime > Number(new Date());            if (isLocked) {              // Unlock the user              Meteor.call('unlockUser', userId, (error) => {                if (error) {                  console.error('Error unlocking user:', error);                }              });            } else {              // Lock the user - this is optional, you may want to only allow unlocking              // If you want to implement locking too, you would need a server method for it              // For now, we'll leave this as a no-op            }        },      },    ];  },}).register('peopleRow');BlazeComponent.extendComponent({  onCreated() {},  teamsDatas() {    const ret = ReactiveCache.getTeams({}, {sort: { teamDisplayName: 1 }});    return ret;  },  events() {    return [      {        'click #cancelBtn': function(){          let selectedElt = document.getElementById("jsteamsUser");          document.getElementById("divAddOrRemoveTeamContainer").style.display = 'none';        },        'click #addTeamBtn': function(){          let selectedElt;          let selectedEltValue;          let selectedEltValueId;          let userTms = [];          let currentUser;          let currUserTeamIndex;          selectedElt = document.getElementById("jsteamsUser");          selectedEltValue = selectedElt.options[selectedElt.selectedIndex].text;          selectedEltValueId = selectedElt.options[selectedElt.selectedIndex].value;          if(document.getElementById('addAction').checked){            for(let i = 0; i < selectedUserChkBoxUserIds.length; i++){              currentUser = ReactiveCache.getUser(selectedUserChkBoxUserIds[i]);              userTms = currentUser.teams;              if(userTms == undefined || userTms.length == 0){                userTms = [];                userTms.push({                  "teamId": selectedEltValueId,                  "teamDisplayName": selectedEltValue,                })              }              else if(userTms.length > 0)              {                currUserTeamIndex = userTms.findIndex(function(t){ return t.teamId == selectedEltValueId});                if(currUserTeamIndex == -1){                  userTms.push({                    "teamId": selectedEltValueId,                    "teamDisplayName": selectedEltValue,                  });                }              }              Users.update(selectedUserChkBoxUserIds[i], {                $set:{                  teams: userTms                }              });            }          }          else{            for(let i = 0; i < selectedUserChkBoxUserIds.length; i++){              currentUser = ReactiveCache.getUser(selectedUserChkBoxUserIds[i]);              userTms = currentUser.teams;              if(userTms !== undefined || userTms.length > 0)              {                currUserTeamIndex = userTms.findIndex(function(t){ return t.teamId == selectedEltValueId});                if(currUserTeamIndex != -1){                  userTms.splice(currUserTeamIndex, 1);                }              }              Users.update(selectedUserChkBoxUserIds[i], {                $set:{                  teams: userTms                }              });            }          }          document.getElementById("divAddOrRemoveTeamContainer").style.display = 'none';        },      },    ];  },}).register('modifyTeamsUsers');BlazeComponent.extendComponent({  events() {    return [      {        'click a.new-org': Popup.open('newOrg'),      },    ];  },}).register('newOrgRow');BlazeComponent.extendComponent({  events() {    return [      {        'click a.new-team': Popup.open('newTeam'),      },    ];  },}).register('newTeamRow');BlazeComponent.extendComponent({  events() {    return [      {        'click a.new-user': Popup.open('newUser'),      },    ];  },}).register('newUserRow');BlazeComponent.extendComponent({  events() {    return [      {        'click .allUserChkBox': function(ev){          selectedUserChkBoxUserIds = [];          const checkboxes = document.getElementsByClassName("selectUserChkBox");          if(ev.currentTarget){            if(ev.currentTarget.checked){              for (let i=0; i<checkboxes.length; i++) {                if (!checkboxes[i].disabled) {                 selectedUserChkBoxUserIds.push(checkboxes[i].id);                 checkboxes[i].checked = true;                }             }            }            else{              for (let i=0; i<checkboxes.length; i++) {                if (!checkboxes[i].disabled) {                 checkboxes[i].checked = false;                }             }            }          }          if(selectedUserChkBoxUserIds.length > 0)            document.getElementById("divAddOrRemoveTeam").style.display = 'block';          else            document.getElementById("divAddOrRemoveTeam").style.display = 'none';        },      },    ];  },}).register('selectAllUser');Template.editOrgPopup.events({  submit(event, templateInstance) {    event.preventDefault();    const org = ReactiveCache.getOrg(this.orgId);    const orgDisplayName = templateInstance      .find('.js-orgDisplayName')      .value.trim();    const orgDesc = templateInstance.find('.js-orgDesc').value.trim();    const orgShortName = templateInstance.find('.js-orgShortName').value.trim();    const orgAutoAddUsersWithDomainName = templateInstance.find('.js-orgAutoAddUsersWithDomainName').value.trim();    const orgWebsite = templateInstance.find('.js-orgWebsite').value.trim();    const orgIsActive = templateInstance.find('.js-org-isactive').value.trim() == 'true';    const isChangeOrgDisplayName = orgDisplayName !== org.orgDisplayName;    const isChangeOrgDesc = orgDesc !== org.orgDesc;    const isChangeOrgShortName = orgShortName !== org.orgShortName;    const isChangeOrgAutoAddUsersWithDomainName = orgAutoAddUsersWithDomainName !== org.orgAutoAddUsersWithDomainName;    const isChangeOrgWebsite = orgWebsite !== org.orgWebsite;    const isChangeOrgIsActive = orgIsActive !== org.orgIsActive;    if (      isChangeOrgDisplayName ||      isChangeOrgDesc ||      isChangeOrgShortName ||      isChangeOrgAutoAddUsersWithDomainName ||      isChangeOrgWebsite ||      isChangeOrgIsActive    ) {      Meteor.call(        'setOrgAllFields',        org,        orgDisplayName,        orgDesc,        orgShortName,        orgAutoAddUsersWithDomainName,        orgWebsite,        orgIsActive,      );    }    Popup.back();  },});Template.editTeamPopup.events({  submit(event, templateInstance) {    event.preventDefault();    const team = ReactiveCache.getTeam(this.teamId);    const teamDisplayName = templateInstance      .find('.js-teamDisplayName')      .value.trim();    const teamDesc = templateInstance.find('.js-teamDesc').value.trim();    const teamShortName = templateInstance      .find('.js-teamShortName')      .value.trim();    const teamWebsite = templateInstance.find('.js-teamWebsite').value.trim();    const teamIsActive =      templateInstance.find('.js-team-isactive').value.trim() == 'true';    const isChangeTeamDisplayName = teamDisplayName !== team.teamDisplayName;    const isChangeTeamDesc = teamDesc !== team.teamDesc;    const isChangeTeamShortName = teamShortName !== team.teamShortName;    const isChangeTeamWebsite = teamWebsite !== team.teamWebsite;    const isChangeTeamIsActive = teamIsActive !== team.teamIsActive;    if (      isChangeTeamDisplayName ||      isChangeTeamDesc ||      isChangeTeamShortName ||      isChangeTeamWebsite ||      isChangeTeamIsActive    ) {      Meteor.call(        'setTeamAllFields',        team,        teamDisplayName,        teamDesc,        teamShortName,        teamWebsite,        teamIsActive,      );    }    Popup.back();  },});Template.editUserPopup.events({  submit(event, templateInstance) {    event.preventDefault();    const user = ReactiveCache.getUser(this.userId);    const username = templateInstance.find('.js-profile-username').value.trim();    const fullname = templateInstance.find('.js-profile-fullname').value.trim();    const initials = templateInstance.find('.js-profile-initials').value.trim();    const password = templateInstance.find('.js-profile-password').value;    const isAdmin = templateInstance.find('.js-profile-isadmin').value.trim();    const isActive = templateInstance.find('.js-profile-isactive').value.trim();    const email = templateInstance.find('.js-profile-email').value.trim();    const verified = templateInstance.find('.js-profile-email-verified').value.trim();    const authentication = templateInstance.find('.js-authenticationMethod').value.trim();    const importUsernames = templateInstance.find('.js-import-usernames').value.trim();    const userOrgs = templateInstance.find('.js-userOrgs').value.trim();    const userOrgsIds = templateInstance.find('.js-userOrgIds').value.trim();    const userTeams = templateInstance.find('.js-userteams').value.trim();    const userTeamsIds = templateInstance.find('.js-userteamIds').value.trim();    const isChangePassword = password.length > 0;    const isChangeUserName = username !== user.username;    const isChangeInitials = initials.length > 0;    const isChangeEmailVerified = verified !== user.emails[0].verified;    // If previously email address has not been set, it is undefined,    // check for undefined, and allow adding email address.    const isChangeEmail =      email.toLowerCase() !==      (typeof user.emails !== 'undefined'        ? user.emails[0].address.toLowerCase()        : false);    Users.update(this.userId, {      $set: {        'profile.fullname': fullname,        isAdmin: isAdmin === 'true',        loginDisabled: isActive === 'true',        authenticationMethod: authentication,        importUsernames: Users.parseImportUsernames(importUsernames),      },    });    let userTeamsList = userTeams.split(",");    let userTeamsIdsList = userTeamsIds.split(",");    let userTms = [];    if(userTeams != ''){      for(let i = 0; i < userTeamsList.length; i++){        userTms.push({          "teamId": userTeamsIdsList[i],          "teamDisplayName": userTeamsList[i],        })      }    }    Users.update(this.userId, {      $set:{        teams: userTms      }    });    let userOrgsList = userOrgs.split(",");    let userOrgsIdsList = userOrgsIds.split(",");    let userOrganizations = [];    if(userOrgs != ''){      for(let i = 0; i < userOrgsList.length; i++){        userOrganizations.push({          "orgId": userOrgsIdsList[i],          "orgDisplayName": userOrgsList[i],        })      }    }    Users.update(this.userId, {      $set:{        orgs: userOrganizations      }    });    if (isChangePassword) {      Meteor.call('setPassword', password, this.userId);    }    if (isChangeEmailVerified) {      Meteor.call('setEmailVerified', email, verified === 'true', this.userId);    }    if (isChangeInitials) {      Meteor.call('setInitials', initials, this.userId);    }    if (isChangeUserName && isChangeEmail) {      Meteor.call(        'setUsernameAndEmail',        username,        email.toLowerCase(),        this.userId,        function (error) {          const usernameMessageElement = templateInstance.$('.username-taken');          const emailMessageElement = templateInstance.$('.email-taken');          if (error) {            const errorElement = error.error;            if (errorElement === 'username-already-taken') {              usernameMessageElement.show();              emailMessageElement.hide();            } else if (errorElement === 'email-already-taken') {              usernameMessageElement.hide();              emailMessageElement.show();            }          } else {            usernameMessageElement.hide();            emailMessageElement.hide();            Popup.back();          }        },      );    } else if (isChangeUserName) {      Meteor.call('setUsername', username, this.userId, function (error) {        const usernameMessageElement = templateInstance.$('.username-taken');        if (error) {          const errorElement = error.error;          if (errorElement === 'username-already-taken') {            usernameMessageElement.show();          }        } else {          usernameMessageElement.hide();          Popup.back();        }      });    } else if (isChangeEmail) {      Meteor.call(        'setEmail',        email.toLowerCase(),        this.userId,        function (error) {          const emailMessageElement = templateInstance.$('.email-taken');          if (error) {            const errorElement = error.error;            if (errorElement === 'email-already-taken') {              emailMessageElement.show();            }          } else {            emailMessageElement.hide();            Popup.back();          }        },      );    } else Popup.back();  },  'click #addUserOrg'(event) {    event.preventDefault();    userOrgsTeamsAction = "addOrg";    document.getElementById("jsOrgs").style.display = 'block';    document.getElementById("jsTeams").style.display = 'none';  },  'click #removeUserOrg'(event) {    event.preventDefault();    userOrgsTeamsAction = "removeOrg";    document.getElementById("jsOrgs").style.display = 'block';    document.getElementById("jsTeams").style.display = 'none';  },  'click #addUserTeam'(event) {    event.preventDefault();    userOrgsTeamsAction = "addTeam";    document.getElementById("jsTeams").style.display = 'block';    document.getElementById("jsOrgs").style.display = 'none';  },  'click #removeUserTeam'(event) {    event.preventDefault();    userOrgsTeamsAction = "removeTeam";    document.getElementById("jsTeams").style.display = 'block';    document.getElementById("jsOrgs").style.display = 'none';  },  'change #jsOrgs'(event) {    event.preventDefault();    UpdateUserOrgsOrTeamsElement();  },  'change #jsTeams'(event) {    event.preventDefault();    UpdateUserOrgsOrTeamsElement();  },});UpdateUserOrgsOrTeamsElement = function(isNewUser = false){  let selectedElt;  let selectedEltValue;  let selectedEltValueId;  let inputElt;  let inputEltId;  let lstInputValues = [];  let lstInputValuesIds = [];  let index;  let indexId;  switch(userOrgsTeamsAction)  {    case "addOrg":    case "removeOrg":      inputElt = !isNewUser ? document.getElementById("jsUserOrgsInPut") : document.getElementById("jsUserOrgsInPutNewUser");      inputEltId = !isNewUser ? document.getElementById("jsUserOrgIdsInPut") : document.getElementById("jsUserOrgIdsInPutNewUser");      selectedElt = !isNewUser ? document.getElementById("jsOrgs") : document.getElementById("jsOrgsNewUser");      break;    case "addTeam":    case "removeTeam":      inputElt = !isNewUser ? document.getElementById("jsUserTeamsInPut") : document.getElementById("jsUserTeamsInPutNewUser");      inputEltId = !isNewUser ? document.getElementById("jsUserTeamIdsInPut") : document.getElementById("jsUserTeamIdsInPutNewUser");      selectedElt = !isNewUser ? document.getElementById("jsTeams") : document.getElementById("jsTeamsNewUser");      break;    default:      break;  }  selectedEltValue = selectedElt.options[selectedElt.selectedIndex].text;  selectedEltValueId = selectedElt.options[selectedElt.selectedIndex].value;  lstInputValues = inputElt.value.trim().split(",");  if(lstInputValues.length == 1 && lstInputValues[0] == ''){    lstInputValues = [];  }  lstInputValuesIds = inputEltId.value.trim().split(",");  if(lstInputValuesIds.length == 1 && lstInputValuesIds[0] == ''){    lstInputValuesIds = [];  }  index = lstInputValues.indexOf(selectedEltValue);  indexId = lstInputValuesIds.indexOf(selectedEltValueId);  if(userOrgsTeamsAction == "addOrg" || userOrgsTeamsAction == "addTeam"){    if(index <= -1 && selectedEltValueId != "-1"){      lstInputValues.push(selectedEltValue);    }    if(indexId <= -1 && selectedEltValueId != "-1"){      lstInputValuesIds.push(selectedEltValueId);    }  }  else{    if(index > -1 && selectedEltValueId != "-1"){      lstInputValues.splice(index, 1);    }    if(indexId > -1 && selectedEltValueId != "-1"){      lstInputValuesIds.splice(indexId, 1);    }  }  if(lstInputValues.length > 0){    inputElt.value = lstInputValues.join(",");  }  else{    inputElt.value = "";  }  if(lstInputValuesIds.length > 0){    inputEltId.value = lstInputValuesIds.join(",");  }  else{    inputEltId.value = "";  }  selectedElt.value = "-1";  selectedElt.style.display = "none";}Template.newOrgPopup.events({  submit(event, templateInstance) {    event.preventDefault();    const orgDisplayName = templateInstance      .find('.js-orgDisplayName')      .value.trim();    const orgDesc = templateInstance.find('.js-orgDesc').value.trim();    const orgShortName = templateInstance.find('.js-orgShortName').value.trim();    const orgAutoAddUsersWithDomainName = templateInstance.find('.js-orgAutoAddUsersWithDomainName').value.trim();    const orgWebsite = templateInstance.find('.js-orgWebsite').value.trim();    const orgIsActive =      templateInstance.find('.js-org-isactive').value.trim() == 'true';    Meteor.call(      'setCreateOrg',      orgDisplayName,      orgDesc,      orgShortName,      orgAutoAddUsersWithDomainName,      orgWebsite,      orgIsActive,    );    Popup.back();  },});Template.newTeamPopup.events({  submit(event, templateInstance) {    event.preventDefault();    const teamDisplayName = templateInstance      .find('.js-teamDisplayName')      .value.trim();    const teamDesc = templateInstance.find('.js-teamDesc').value.trim();    const teamShortName = templateInstance      .find('.js-teamShortName')      .value.trim();    const teamWebsite = templateInstance.find('.js-teamWebsite').value.trim();    const teamIsActive =      templateInstance.find('.js-team-isactive').value.trim() == 'true';    Meteor.call(      'setCreateTeam',      teamDisplayName,      teamDesc,      teamShortName,      teamWebsite,      teamIsActive,    );    Popup.back();  },});Template.newUserPopup.events({  submit(event, templateInstance) {    event.preventDefault();    const fullname = templateInstance.find('.js-profile-fullname').value.trim();    const username = templateInstance.find('.js-profile-username').value.trim();    const initials = templateInstance.find('.js-profile-initials').value.trim();    const password = templateInstance.find('.js-profile-password').value;    const isAdmin = templateInstance.find('.js-profile-isadmin').value.trim();    const isActive = templateInstance.find('.js-profile-isactive').value.trim();    const email = templateInstance.find('.js-profile-email').value.trim();    const importUsernames = Users.parseImportUsernames(      templateInstance.find('.js-import-usernames').value,    );    const userOrgs = templateInstance.find('.js-userOrgsNewUser').value.trim();    const userOrgsIds = templateInstance.find('.js-userOrgIdsNewUser').value.trim();    const userTeams = templateInstance.find('.js-userteamsNewUser').value.trim();    const userTeamsIds = templateInstance.find('.js-userteamIdsNewUser').value.trim();    let userTeamsList = userTeams.split(",");    let userTeamsIdsList = userTeamsIds.split(",");    let userTms = [];    for(let i = 0; i < userTeamsList.length; i++){      if(!!userTeamsIdsList[i] && !!userTeamsList[i]) {        userTms.push({          "teamId": userTeamsIdsList[i],          "teamDisplayName": userTeamsList[i],        })      }    }    let userOrgsList = userOrgs.split(",");    let userOrgsIdsList = userOrgsIds.split(",");    let userOrganizations = [];    for(let i = 0; i < userOrgsList.length; i++){      if(!!userOrgsIdsList[i] && !!userOrgsList[i]) {        userOrganizations.push({          "orgId": userOrgsIdsList[i],          "orgDisplayName": userOrgsList[i],        })      }    }    Meteor.call(      'setCreateUser',      fullname,      username,      initials,      password,      isAdmin,      isActive,      email.toLowerCase(),      importUsernames,      userOrganizations,      userTms,      function(error) {        const usernameMessageElement = templateInstance.$('.username-taken');        const emailMessageElement = templateInstance.$('.email-taken');        if (error) {          const errorElement = error.error;          if (errorElement === 'username-already-taken') {            usernameMessageElement.show();            emailMessageElement.hide();          } else if (errorElement === 'email-already-taken') {            usernameMessageElement.hide();            emailMessageElement.show();          }        } else {          usernameMessageElement.hide();          emailMessageElement.hide();          Popup.back();        }      },    );    Popup.back();  },  'click #addUserOrgNewUser'(event) {    event.preventDefault();    userOrgsTeamsAction = "addOrg";    document.getElementById("jsOrgsNewUser").style.display = 'block';    document.getElementById("jsTeamsNewUser").style.display = 'none';  },  'click #removeUserOrgNewUser'(event) {    event.preventDefault();    userOrgsTeamsAction = "removeOrg";    document.getElementById("jsOrgsNewUser").style.display = 'block';    document.getElementById("jsTeamsNewUser").style.display = 'none';  },  'click #addUserTeamNewUser'(event) {    event.preventDefault();    userOrgsTeamsAction = "addTeam";    document.getElementById("jsTeamsNewUser").style.display = 'block';    document.getElementById("jsOrgsNewUser").style.display = 'none';  },  'click #removeUserTeamNewUser'(event) {    event.preventDefault();    userOrgsTeamsAction = "removeTeam";    document.getElementById("jsTeamsNewUser").style.display = 'block';    document.getElementById("jsOrgsNewUser").style.display = 'none';  },  'change #jsOrgsNewUser'(event) {    event.preventDefault();    UpdateUserOrgsOrTeamsElement(true);  },  'change #jsTeamsNewUser'(event) {    event.preventDefault();    UpdateUserOrgsOrTeamsElement(true);  },});Template.settingsOrgPopup.events({  'click #deleteButton'(event) {    event.preventDefault();    if (ReactiveCache.getUsers({"orgs.orgId": this.orgId}).length > 0)    {      let orgClassList = document.getElementById("deleteOrgWarningMessage").classList;      if(orgClassList.contains('hide'))      {        orgClassList.remove('hide');        document.getElementById("deleteOrgWarningMessage").style.color = "red";      }      return;    }    Org.remove(this.orgId);    Popup.back();  }});Template.settingsTeamPopup.events({  'click #deleteButton'(event) {    event.preventDefault();    if (ReactiveCache.getUsers({"teams.teamId": this.teamId}).length > 0)    {      let teamClassList = document.getElementById("deleteTeamWarningMessage").classList;      if(teamClassList.contains('hide'))      {        teamClassList.remove('hide');        document.getElementById("deleteTeamWarningMessage").style.color = "red";      }      return;    }    Team.remove(this.teamId);    Popup.back();  }});Template.settingsUserPopup.events({  'click .impersonate-user'(event) {    event.preventDefault();    Meteor.call('impersonate', this.userId, (err) => {      if (!err) {        FlowRouter.go('/');        Meteor.connection.setUserId(this.userId);      }    });  },  'click #deleteButton'(event) {    event.preventDefault();    // Use secure server method instead of direct client-side removal    Meteor.call('removeUser', this.userId, (error, result) => {      if (error) {        if (process.env.DEBUG === 'true') {          console.error('Error removing user:', error);        }        // Show error message to user        if (error.error === 'not-authorized') {          alert('You are not authorized to delete this user.');        } else if (error.error === 'user-not-found') {          alert('User not found.');        } else if (error.error === 'not-authorized' && error.reason === 'Cannot delete the last administrator') {          alert('Cannot delete the last administrator.');        } else {          alert('Error deleting user: ' + error.reason);        }      } else {        if (process.env.DEBUG === 'true') {          console.log('User deleted successfully:', result);        }        Popup.back();      }    });  },});Template.settingsUserPopup.helpers({  user() {    return ReactiveCache.getUser(this.userId);  },  authentications() {    return Template.instance().authenticationMethods.get();  },  isSelected(match) {    const userId = Template.instance().data.userId;    const selected = ReactiveCache.getUser(userId).authenticationMethod;    return selected === match;  },  isLdap() {    const userId = Template.instance().data.userId;    const selected = ReactiveCache.getUser(userId).authenticationMethod;    return selected === 'ldap';  },  errorMessage() {    return Template.instance().errorMessage.get();  },});
 |