diff options
Diffstat (limited to 'trunk/etherpad/src/etherpad/pro/pro_accounts.js')
-rw-r--r-- | trunk/etherpad/src/etherpad/pro/pro_accounts.js | 496 |
1 files changed, 0 insertions, 496 deletions
diff --git a/trunk/etherpad/src/etherpad/pro/pro_accounts.js b/trunk/etherpad/src/etherpad/pro/pro_accounts.js deleted file mode 100644 index 2024970..0000000 --- a/trunk/etherpad/src/etherpad/pro/pro_accounts.js +++ /dev/null @@ -1,496 +0,0 @@ -/** - * Copyright 2009 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS-IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// library for pro accounts - -import("funhtml.*"); -import("sqlbase.sqlobj"); -import("sqlbase.sqlcommon.inTransaction"); -import("email.sendEmail"); -import("cache_utils.syncedWithCache"); -import("stringutils.*"); - -import("etherpad.globals.*"); -import("etherpad.sessions"); -import("etherpad.sessions.getSession"); -import("etherpad.utils.*"); -import("etherpad.pro.domains"); -import("etherpad.control.pro.account_control"); -import("etherpad.pro.pro_utils"); -import("etherpad.pro.pro_quotas"); -import("etherpad.pad.padusers"); -import("etherpad.log"); -import("etherpad.billing.team_billing"); - -jimport("org.mindrot.BCrypt"); -jimport("java.lang.System.out.println"); - -function _dmesg(m) { - if (!isProduction()) { - println(m); - } -} - -function _computePasswordHash(p) { - var pwh; - pwh = BCrypt.hashpw(p, BCrypt.gensalt(10)); - return pwh; -} - -function _withCache(name, fn) { - return syncedWithCache('pro_accounts.'+name, fn); -} - -//---------------------------------------------------------------- -// validation -//---------------------------------------------------------------- - -function validateEmail(email) { - if (!email) { return "Email is required."; } - if (!isValidEmail(email)) { return "\""+email+"\" does not look like a valid email address."; } - return null; -} - -function validateFullName(name) { - if (!name) { return "Full name is required."; } - if (name.length < 2) { return "Full name must be at least 2 characters."; } - return null; -} - -function validatePassword(p) { - if (!p) { return "Password is required."; } - if (p.length < 6) { return "Passwords must be at least 6 characters."; } - return null; -} - -function validateEmailDomainPair(email, domainId) { - // TODO: make sure the same email address cannot exist more than once within - // the same domainid. -} - -/* if domainId is null, then use domainId of current request. */ -function createNewAccount(domainId, fullName, email, password, isAdmin) { - if (!domainId) { - domainId = domains.getRequestDomainId(); - } - email = trim(email); - isAdmin = !!isAdmin; // convert to bool - - // validation - var e; - e = validateEmail(email); if (e) { throw Error(e); } - e = validateFullName(fullName); if (e) { throw Error(e); } - e = validatePassword(password); if (e) { throw Error(e); } - - // xss normalization - fullName = toHTML(fullName); - - // make sure account does not already exist on this domain. - var ret = inTransaction(function() { - var existingAccount = getAccountByEmail(email, domainId); - if (existingAccount) { - throw Error("There is already an account with that email address."); - } - // No existing account. Proceed. - var now = new Date(); - var account = { - domainId: domainId, - fullName: fullName, - email: email, - passwordHash: _computePasswordHash(password), - createdDate: now, - isAdmin: isAdmin - }; - return sqlobj.insert('pro_accounts', account); - }); - - _withCache('does-domain-admin-exist', function(cache) { - delete cache[domainId]; - }); - - pro_quotas.updateAccountUsageCount(domainId); - updateCachedActiveCount(domainId); - - if (ret) { - log.custom('pro-accounts', - {type: "account-created", - accountId: ret, - domainId: domainId, - name: fullName, - email: email, - admin: isAdmin}); - } - - return ret; -} - -function _checkAccess(account) { - if (sessions.isAnEtherpadAdmin()) { - return; - } - if (account.domainId != domains.getRequestDomainId()) { - throw Error("access denied"); - } -} - -function setPassword(account, newPass) { - _checkAccess(account); - var passHash = _computePasswordHash(newPass); - sqlobj.update('pro_accounts', {id: account.id}, {passwordHash: passHash}); - markDirtySessionAccount(account.id); -} - -function setTempPassword(account, tempPass) { - _checkAccess(account); - var tempPassHash = _computePasswordHash(tempPass); - sqlobj.update('pro_accounts', {id: account.id}, {tempPassHash: tempPassHash}); - markDirtySessionAccount(account.id); -} - -function setEmail(account, newEmail) { - _checkAccess(account); - sqlobj.update('pro_accounts', {id: account.id}, {email: newEmail}); - markDirtySessionAccount(account.id); -} - -function setFullName(account, newName) { - _checkAccess(account); - sqlobj.update('pro_accounts', {id: account.id}, {fullName: newName}); - markDirtySessionAccount(account.id); -} - -function setIsAdmin(account, newVal) { - _checkAccess(account); - sqlobj.update('pro_accounts', {id: account.id}, {isAdmin: newVal}); - markDirtySessionAccount(account.id); -} - -function setDeleted(account) { - _checkAccess(account); - if (!isNumeric(account.id)) { - throw new Error("Invalid account id: "+account.id); - } - sqlobj.update('pro_accounts', {id: account.id}, {isDeleted: true}); - markDirtySessionAccount(account.id); - pro_quotas.updateAccountUsageCount(account.domainId); - updateCachedActiveCount(account.domainId); - - log.custom('pro-accounts', - {type: "account-deleted", - accountId: account.id, - domainId: account.domainId, - name: account.fullName, - email: account.email, - admin: account.isAdmin, - createdDate: account.createdDate.getTime()}); -} - -//---------------------------------------------------------------- - -function doesAdminExist() { - var domainId = domains.getRequestDomainId(); - return _withCache('does-domain-admin-exist', function(cache) { - if (cache[domainId] === undefined) { - _dmesg("cache miss for doesAdminExist (domainId="+domainId+")"); - var admins = sqlobj.selectMulti('pro_accounts', {domainId: domainId, isAdmin: true}, {}); - cache[domainId] = (admins.length > 0); - } - return cache[domainId] - }); -} - -function getSessionProAccount() { - if (sessions.isAnEtherpadAdmin()) { - return getEtherpadAdminAccount(); - } - var account = getSession().proAccount; - if (!account) { - return null; - } - if (account.isDeleted) { - delete getSession().proAccount; - return null; - } - return account; -} - -function isAccountSignedIn() { - if (getSessionProAccount()) { - return true; - } else { - return false; - } -} - -function isAdminSignedIn() { - return isAccountSignedIn() && getSessionProAccount().isAdmin; -} - -function requireAccount(message) { - if ((request.path == "/ep/account/sign-in") || - (request.path == "/ep/account/sign-out") || - (request.path == "/ep/account/guest-sign-in") || - (request.path == "/ep/account/guest-knock") || - (request.path == "/ep/account/forgot-password")) { - return; - } - - function checkSessionAccount() { - if (!getSessionProAccount()) { - if (message) { - account_control.setSigninNotice(message); - } - response.redirect('/ep/account/sign-in?cont='+encodeURIComponent(request.url)); - } - } - - checkSessionAccount(); - - if (getSessionProAccount().domainId != domains.getRequestDomainId()) { - // This should theoretically never happen unless the account is spoofing cookies / trying to - // hack the site. - pro_utils.renderFramedMessage("Permission denied."); - response.stop(); - } - // update dirty session account if necessary - _withCache('dirty-session-accounts', function(cache) { - var uid = getSessionProAccount().id; - if (cache[uid]) { - reloadSessionAccountData(uid); - cache[uid] = false; - } - }); - - // need to check again in case dirty update caused account to be marked - // deleted. - checkSessionAccount(); -} - -function requireAdminAccount() { - requireAccount(); - if (!getSessionProAccount().isAdmin) { - pro_utils.renderFramedMessage("Permission denied."); - response.stop(); - } -} - -/* returns undefined on success, error string otherise. */ -function authenticateSignIn(email, password) { - var accountRecord = getAccountByEmail(email, null); - if (!accountRecord) { - return "Account not found: "+email; - } - - if (BCrypt.checkpw(password, accountRecord.passwordHash) != true) { - return "Incorrect password. Please try again."; - } - - signInSession(accountRecord); - - return undefined; // success -} - -function signOut() { - delete getSession().proAccount; -} - -function authenticateTempSignIn(uid, tempPass) { - var emsg = "That password reset link that is no longer valid."; - - var account = getAccountById(uid); - if (!account) { - return emsg+" (Account not found.)"; - } - if (account.domainId != domains.getRequestDomainId()) { - return emsg+" (Wrong domain.)"; - } - if (!account.tempPassHash) { - return emsg+" (Expired.)"; - } - if (BCrypt.checkpw(tempPass, account.tempPassHash) != true) { - return emsg+" (Bad temp pass.)"; - } - - signInSession(account); - - getSession().accountMessage = "Please choose a new password"; - getSession().changePass = true; - - response.redirect("/ep/account/"); -} - -function signInSession(account) { - account.lastLoginDate = new Date(); - account.tempPassHash = null; - sqlobj.updateSingle('pro_accounts', {id: account.id}, account); - reloadSessionAccountData(account.id); - padusers.notifySignIn(); -} - -function listAllDomainAccounts(domainId) { - if (domainId === undefined) { - domainId = domains.getRequestDomainId(); - } - var records = sqlobj.selectMulti('pro_accounts', - {domainId: domainId, isDeleted: false}, {}); - return records; -} - -function listAllDomainAdmins(domainId) { - if (domainId === undefined) { - domainId = domains.getRequestDomainId(); - } - var records = sqlobj.selectMulti('pro_accounts', - {domainId: domainId, isDeleted: false, isAdmin: true}, - {}); - return records; -} - -function getActiveCount(domainId) { - var records = sqlobj.selectMulti('pro_accounts', - {domainId: domainId, isDeleted: false}, {}); - return records.length; -} - -/* getAccountById works for deleted and non-deleted accounts. - * The assumption is that cases whewre you look up an account by ID, you - * want the account info even if the account has been deleted. For - * example, when asking who created a pad. - */ -function getAccountById(accountId) { - var r = sqlobj.selectSingle('pro_accounts', {id: accountId}); - if (r) { - return r; - } else { - return undefined; - } -} - -/* getting an account by email only returns the account if it is - * not deleted. The assumption is that when you look up an account by - * email address, you only want active accounts. Furthermore, some - * deleted accounts may match a given email, but only one non-deleted - * account should ever match a single (email,domainId) pair. - */ -function getAccountByEmail(email, domainId) { - if (!domainId) { - domainId = domains.getRequestDomainId(); - } - var r = sqlobj.selectSingle('pro_accounts', {domainId: domainId, email: email, isDeleted: false}); - if (r) { - return r; - } else { - return undefined; - } -} - -function getFullNameById(id) { - if (!id) { - return null; - } - - return _withCache('names-by-id', function(cache) { - if (cache[id] === undefined) { - _dmesg("cache miss for getFullNameById (accountId="+id+")"); - var r = getAccountById(id); - if (r) { - cache[id] = r.fullName; - } else { - cache[id] = false; - } - } - if (cache[id]) { - return cache[id]; - } else { - return null; - } - }); -} - -function getTempSigninUrl(account, tempPass) { - return [ - 'https://', httpsHost(pro_utils.getFullProHost()), '/ep/account/sign-in?', - 'uid=', account.id, '&tp=', tempPass - ].join(''); -} - - -// TODO: this session account object storage / dirty cache is a -// ridiculous hack. What we should really do is have a caching/access -// layer for accounts similar to accessPad() and accessProPadMeta(), and -// have that abstraction take care of caching and marking accounts as -// dirty. This can be incorporated into getSessionProAccount(), and we -// should actually refactor that into accessSessionProAccount(). - -/* will force session data for this account to be updated next time that - * account requests a page. */ -function markDirtySessionAccount(uid) { - var domainId = domains.getRequestDomainId(); - - _withCache('dirty-session-accounts', function(cache) { - cache[uid] = true; - }); - _withCache('names-by-id', function(cache) { - delete cache[uid]; - }); - _withCache('does-domain-admin-exist', function(cache) { - delete cache[domainId]; - }); -} - -function reloadSessionAccountData(uid) { - if (!uid) { - uid = getSessionProAccount().id; - } - getSession().proAccount = getAccountById(uid); -} - -function getAllAccountsWithEmail(email) { - var accountRecords = sqlobj.selectMulti('pro_accounts', {email: email, isDeleted: false}, {}); - return accountRecords; -} - -function getEtherpadAdminAccount() { - return { - id: 0, - isAdmin: true, - fullName: "ETHERPAD ADMIN", - email: "support@pad.spline.inf.fu-berlin.de", - domainId: domains.getRequestDomainId(), - isDeleted: false - }; -} - -function getCachedActiveCount(domainId) { - return _withCache('user-counts.'+domainId, function(c) { - if (!c.count) { - c.count = getActiveCount(domainId); - } - return c.count; - }); -} - -function updateCachedActiveCount(domainId) { - _withCache('user-counts.'+domainId, function(c) { - c.count = getActiveCount(domainId); - }); -} - - - - - - |