diff options
author | pzread <netfirewall@gmail.com> | 2013-06-09 01:48:00 +0800 |
---|---|---|
committer | pzread <netfirewall@gmail.com> | 2013-06-09 01:48:00 +0800 |
commit | 8cf636373548c8e3484a137268ddd041d12bbe4a (patch) | |
tree | 073d3d4cbca57798ef737a6ec3702621c66fba21 /src/py/user.py | |
parent | 9fa7badc787ec364d58f65b95355c8725ad75a9c (diff) | |
download | taiwan-online-judge-8cf636373548c8e3484a137268ddd041d12bbe4a.tar.gz taiwan-online-judge-8cf636373548c8e3484a137268ddd041d12bbe4a.tar.zst taiwan-online-judge-8cf636373548c8e3484a137268ddd041d12bbe4a.zip |
Add user module. Stable sendfile. Change async. Change imc call
Diffstat (limited to 'src/py/user.py')
-rwxr-xr-x | src/py/user.py | 336 |
1 files changed, 336 insertions, 0 deletions
diff --git a/src/py/user.py b/src/py/user.py new file mode 100755 index 0000000..45e195a --- /dev/null +++ b/src/py/user.py @@ -0,0 +1,336 @@ +import psycopg2 +from Crypto.Hash import SHA512 + +from tojauth import TOJAuth +from asyncdb import AsyncDB +import imc.proxy +import config + +class User: + auth_accessid = 2 + + USERNAME_LEN_MIN = 5 + USERNAME_LEN_MAX = 50 + PASSWORD_LEN_MIN = 5 + PASSWORD_LEN_MAX = 50 + NICKNAME_LEN_MIN = 1 + NICKNAME_LEN_MAX = 50 + EMAIL_LEN_MIN = 5 + EMAIL_LEN_MAX = 100 + AVATAR_LEN_MIN = 0 + AVATAR_LEN_MAX = 200 + ABOUTME_LEN_MIN = 0 + ABOUTME_LEN_MAX = 1000 + + def __init__(self, mod_iden): + User.instance = self + User.db = AsyncDB(config.CORE_DBNAME, config.CORE_DBUSER, + config.CORE_DBPASSWORD) + User.mod_iden = mod_iden + + @imc.async.caller + def register(self, username, password, nickname, email, avatar, aboutme): + if( + type(username) != str or + type(password) != str or + type(nickname) != str or + type(email) != str or + type(avatar) != str or + type(aboutme) != str + ): + return 'Eparameter' + + if len(username) < self.USERNAME_LEN_MIN: + return 'Eusername_too_short' + elif len(username) > self.USERNAME_LEN_MAX: + return 'Eusername_too_long' + elif len(password) < self.PASSWORD_LEN_MIN: + return 'Epassword_too_short' + elif len(password) > self.PASSWORD_LEN_MAX: + return 'Epassword_too_long' + elif len(nickname) < self.NICKNAME_LEN_MIN: + return 'Enickname_too_short' + elif len(nickname) > self.NICKNAME_LEN_MAX: + return 'Enickname_too_long' + elif len(email) < self.EMAIL_LEN_MIN: + return 'Eemail_too_short' + elif len(email) > self.EMAIL_LEN_MAX: + return 'Eemail_too_long' + elif len(avatar) < self.AVATAR_LEN_MIN: + return 'Eavatar_too_short' + elif len(avatar) > self.AVATAR_LEN_MAX: + return 'Eavatar_too_long' + elif len(aboutme) < self.ABOUTME_LEN_MIN: + return 'Eaboutme_too_short' + elif len(aboutme) > self.ABOUTME_LEN_MAX: + return 'Eaboutme_too_long' + + passhash = self._password_hash(password) + + with TOJAuth.change_current_iden(self.mod_iden): + try: + uid = self._create_user( + username, passhash, nickname, email, avatar, aboutme) + except psycopg2.IntegrityError: + return 'Eusername_already_exists' + + return {'uid' : uid} + + @TOJAuth.check_access(auth_accessid, TOJAuth.ACCESS_EXECUTE) + def _create_user(self, username, passhash, nickname, email, avatar, + aboutme): + roleid = TOJAuth.instance.create_role(username, TOJAuth.ROLETYPE_USER) + + cur = self.db.cursor() + sqlstr = ('INSERT INTO "USER" ("username", "passhash", "nickname", ' + '"email", "avatar", "aboutme", "idenid") ' + 'VALUES (%s, %s, %s, %s, %s, %s, %s) RETURNING "uid";') + sqlarr = (username, passhash, nickname, email, avatar, aboutme, roleid) + cur.execute(sqlstr, sqlarr) + + for data in cur: + uid = data[0] + return uid + + @imc.async.caller + def login(self, username, password): + if( + type(username) != str or + type(password) != str + ): + return 'Eparameter' + + uid = self.get_uid_by_username(username) + if uid == None: + return 'Eno_such_uid' + + passhash = self._password_hash(password) + + cur = self.db.cursor() + sqlstr = ('SELECT "idenid" FROM "USER" WHERE "uid" = %s ' + 'AND "passhash" = %s;') + sqlarr = (uid, passhash) + cur.execute(sqlstr, sqlarr) + + idenid = None + for data in cur: + idenid = data[0] + + if idenid == None: + return 'Ewrong_password' + + linkclass = TOJAuth.get_current_iden()['linkclass'] + linkid = TOJAuth.get_current_iden()['linkid'] + + with TOJAuth.change_current_iden(self.mod_iden): + idendesc = TOJAuth.instance.create_iden( + linkclass, linkid, idenid, TOJAuth.ROLETYPE_USER, {'uid' : uid} + ) + + ret = { + 'idendesc' : idendesc, + 'uid' : uid, + 'hash' : self._uid_passhash_hash(uid, passhash) + } + + return ret + + @imc.async.caller + def cookie_login(self, uid, uphash): + if( + type(uid) != int or + type(uphash) != str + ): + return 'Eparameter' + + idenid = None + real_uphash = None + + cur = self.db.cursor() + sqlstr = ('SELECT "idenid", "passhash" FROM "USER" WHERE "uid" = %s;') + sqlarr = (uid, ) + cur.execute(sqlstr, sqlarr) + + for data in cur: + idenid = data[0] + real_uphash = self._uid_passhash_hash(uid, data[1]) + + if idenid == None: + return 'Eno_such_uid' + + if real_uphash != uphash: + return 'Ewrong_uphash' + + linkclass = TOJAuth.get_current_iden()['linkclass'] + linkid = TOJAuth.get_current_iden()['linkid'] + + with TOJAuth.change_current_iden(self.mod_iden): + idendesc = TOJAuth.instance.create_iden( + linkclass, linkid, idenid, TOJAuth.ROLETYPE_USER, {'uid' : uid} + ) + + ret = { + 'idendesc' : idendesc, + 'uid' : uid, + 'hash' : uphash + } + + return ret + + @imc.async.caller + def get_user_info(self, uid): + if( + type(uid) != int + ): + return 'Eparameter' + + ret = self._get_user_info_by_uid(uid) + if ret == None: + return 'Eno_such_uid' + + return ret + + @imc.async.caller + def set_user_info(self, uid, nickname, email, avatar, aboutme): + if( + type(uid) != int or + type(nickname) != str or + type(email) != str or + type(avatar) != str or + type(aboutme) != str + ): + return 'Eparameter' + + if len(nickname) < self.NICKNAME_LEN_MIN: + return 'Enickname_too_short' + elif len(nickname) > self.NICKNAME_LEN_MAX: + return 'Enickname_too_long' + elif len(email) < self.EMAIL_LEN_MIN: + return 'Eemail_too_short' + elif len(email) > self.EMAIL_LEN_MAX: + return 'Eemail_too_long' + elif len(avatar) < self.AVATAR_LEN_MIN: + return 'Eavatar_too_short' + elif len(avatar) > self.AVATAR_LEN_MAX: + return 'Eavatar_too_long' + elif len(aboutme) < self.ABOUTME_LEN_MIN: + return 'Eaboutme_too_short' + elif len(aboutme) > self.ABOUTME_LEN_MAX: + return 'Eaboutme_too_long' + + idenid = self.get_idenid_by_uid(uid) + if idenid == None: + return 'Eno_such_uid' + + if idenid != TOJAuth.get_current_iden()['idenid']: + TOJAuth.check_access( + self.auth_accessid, TOJAuth.ACCESS_EXECUTE)(lambda x:x)(0) + + cur = self.db.cursor() + sqlstr = ('UPDATE "USER" SET "nickname" = %s, "email" = %s, ' + '"avatar" = %s, "aboutme" = %s WHERE "uid" = %s;') + sqlarr = (nickname, email, avatar, aboutme, uid) + cur.execute(sqlstr, sqlarr) + + @imc.async.caller + def change_user_password(self, uid, old_password, new_password): + if( + type(uid) != int or + type(old_password) != str or + type(new_password) != str + ): + return 'Eparameter' + + if len(new_password) < self.PASSWORD_LEN_MIN: + return 'Epassword_too_short' + elif len(new_password) > self.PASSWORD_LEN_MAX: + return 'Epassword_too_long' + + idenid = self.get_idenid_by_uid(uid) + if idenid == None: + return 'Eno_such_uid' + + if idenid != TOJAuth.get_current_iden()['idenid']: + TOJAuth.check_access( + self.auth_accessid, TOJAuth.ACCESS_EXECUTE)(lambda x:x)(0) + + old_passhash = self._password_hash(old_password) + + cur = self.db.cursor() + sqlstr = ('SELECT "idenid" FROM "USER" WHERE "uid" = %s ' + 'AND "passhash" = %s;') + sqlarr = (uid, old_passhash) + cur.execute(sqlstr, sqlarr) + + idenid = None + for data in cur: + idenid = data[0] + + if idenid == None: + return 'Ewrong_old_password' + + new_passhash = self._password_hash(new_password) + + sqlstr = ('UPDATE "USER" SET "passhash" = %s WHERE "uid" = %s;') + sqlarr = (new_passhash, uid) + cur.execute(sqlstr, sqlarr) + + @imc.async.caller + def oauth_login(self): + raise NotImplementedError + + def _password_hash(self, password): + h = SHA512.new(bytes(password + config.USER_PASSHASH_SALT, 'utf-8')) + return h.hexdigest() + + def _uid_passhash_hash(self, uid, passhash): + return self._password_hash( + 'GENGJIAN_WEISUO_KING^^' + str(uid) + '@E__E@' + passhash + 'Yo!') + + def _get_user_info_by_uid(self, uid): + cur = self.db.cursor() + sqlstr = ('SELECT * FROM "USER" WHERE "uid" = %s;') + sqlarr = (uid, ) + cur.execute(sqlstr, sqlarr) + + ret = None + for data in cur: + ret = {} + ret['uid'] = data[0] + ret['username'] = data[1] + ret['nickname'] = data[3] + ret['email'] = data[4] + ret['avatar'] = data[5] + ret['aboutme'] = data[6] + + return ret + + def get_idenid_by_uid(self, uid): + cur = self.db.cursor() + sqlstr = ('SELECT "idenid" FROM "USER" WHERE "uid" = %s;') + sqlarr = (uid, ) + cur.execute(sqlstr, sqlarr) + + ret = None + for data in cur: + ret = data[0] + + return ret + + def get_uid_by_username(self, username): + cur = self.db.cursor() + sqlstr = ('SELECT "uid" FROM "USER" WHERE "username" = %s;') + sqlarr = (username, ) + cur.execute(sqlstr, sqlarr) + + uid = None + for data in cur: + uid = data[0] + + return uid + + def does_username_exist(self, username): + uid = self.get_uid_by_username(username) + + return uid != None + |