finish token manager
This commit is contained in:
@@ -153,33 +153,6 @@ Common类下的为通用请求接口,一般与用户状态等相关
|
|||||||
|
|
||||||
返回参数:一个bool,表示是否有效
|
返回参数:一个bool,表示是否有效
|
||||||
|
|
||||||
#### isAdmin
|
|
||||||
|
|
||||||
请求地址:`/api/common/isAdmin`
|
|
||||||
|
|
||||||
请求参数:
|
|
||||||
|
|
||||||
|参数名|参数类型|参数解释|
|
|
||||||
|:---|:---|:---|
|
|
||||||
|token|string|用于管理员鉴别的token|
|
|
||||||
|
|
||||||
返回参数:一个bool,表示是否是管理员
|
|
||||||
|
|
||||||
#### changePassword
|
|
||||||
|
|
||||||
请求地址:`/api/common/changePassword`
|
|
||||||
|
|
||||||
请求参数:
|
|
||||||
|
|
||||||
|参数名|参数类型|参数解释|
|
|
||||||
|:---|:---|:---|
|
|
||||||
|token|string|用于用户鉴权的字符串|
|
|
||||||
|password|string|新的明文密码|
|
|
||||||
|
|
||||||
返回参数:一个bool,表示是否修改成功
|
|
||||||
|
|
||||||
此请求的安全性由HTTPS保证。
|
|
||||||
|
|
||||||
### Calendar类
|
### Calendar类
|
||||||
|
|
||||||
Calendar类下的为日历请求接口
|
Calendar类下的为日历请求接口
|
||||||
@@ -568,6 +541,63 @@ Admin类的操作不涉及任何客户端存储,因此不需要lastChange来
|
|||||||
|
|
||||||
返回参数:一个bool表示是否删除成功
|
返回参数:一个bool表示是否删除成功
|
||||||
|
|
||||||
|
### Profile类
|
||||||
|
|
||||||
|
Admin类下的为当前用户一些个人属性的请求接口
|
||||||
|
Profile类的操作不涉及任何客户端存储,因此不需要lastChange来保护。
|
||||||
|
|
||||||
|
#### isAdmin
|
||||||
|
|
||||||
|
请求地址:`/api/profile/isAdmin`
|
||||||
|
|
||||||
|
请求参数:
|
||||||
|
|
||||||
|
|参数名|参数类型|参数解释|
|
||||||
|
|:---|:---|:---|
|
||||||
|
|token|string|用于管理员鉴别的token|
|
||||||
|
|
||||||
|
返回参数:一个bool,表示是否是管理员
|
||||||
|
|
||||||
|
#### changePassword
|
||||||
|
|
||||||
|
请求地址:`/api/profile/changePassword`
|
||||||
|
|
||||||
|
请求参数:
|
||||||
|
|
||||||
|
|参数名|参数类型|参数解释|
|
||||||
|
|:---|:---|:---|
|
||||||
|
|token|string|用于用户鉴权的字符串|
|
||||||
|
|password|string|新的明文密码|
|
||||||
|
|
||||||
|
返回参数:一个bool,表示是否修改成功
|
||||||
|
|
||||||
|
此请求的安全性由HTTPS保证。
|
||||||
|
|
||||||
|
#### getToken
|
||||||
|
|
||||||
|
请求地址:`/api/profile/getToken`
|
||||||
|
|
||||||
|
请求参数:
|
||||||
|
|
||||||
|
|参数名|参数类型|参数解释|
|
||||||
|
|:---|:---|:---|
|
||||||
|
|token|string|用于用户鉴权的字符串|
|
||||||
|
|
||||||
|
返回参数:一个JSON列表,为token表中符合当前提起请求的用户的所有token的条目
|
||||||
|
|
||||||
|
#### deleteToken
|
||||||
|
|
||||||
|
请求地址:`/api/profile/deleteToken`
|
||||||
|
|
||||||
|
请求参数:
|
||||||
|
|
||||||
|
|参数名|参数类型|参数解释|
|
||||||
|
|:---|:---|:---|
|
||||||
|
|token|string|用于用户鉴权的字符串|
|
||||||
|
|deleteToken|string|需要被强制下线的token|
|
||||||
|
|
||||||
|
返回参数:一个bool,表示是否下线成功
|
||||||
|
|
||||||
## 事件循环规则字符串
|
## 事件循环规则字符串
|
||||||
|
|
||||||
事件循环规则字符串 是一串用于描述当前事件循环规则的字符串,通过解析字符串可以计算出整个时间序列。本字符串借鉴了ics设计,但与ics设计毫无相似之处。
|
事件循环规则字符串 是一串用于描述当前事件循环规则的字符串,通过解析字符串可以计算出整个时间序列。本字符串借鉴了ics设计,但与ics设计毫无相似之处。
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ class CalendarDatabase(object):
|
|||||||
return salt
|
return salt
|
||||||
|
|
||||||
@SafeDatabaseOperation
|
@SafeDatabaseOperation
|
||||||
def common_login(self, username, password):
|
def common_login(self, username, password, clientUa, clientIp):
|
||||||
self.cursor.execute('SELECT [ccn_password], [ccn_salt] FROM user WHERE [ccn_name] = ?;', (username, ))
|
self.cursor.execute('SELECT [ccn_password], [ccn_salt] FROM user WHERE [ccn_name] = ?;', (username, ))
|
||||||
(gotten_salt, gotten_password) = self.cursor.fetchone()
|
(gotten_salt, gotten_password) = self.cursor.fetchone()
|
||||||
|
|
||||||
@@ -146,10 +146,12 @@ class CalendarDatabase(object):
|
|||||||
utils.GenerateSalt(), # regenerate a new slat to prevent re-login try
|
utils.GenerateSalt(), # regenerate a new slat to prevent re-login try
|
||||||
username
|
username
|
||||||
))
|
))
|
||||||
self.cursor.execute('INSERT INTO token VALUES (?, ?, ?);', (
|
self.cursor.execute('INSERT INTO token VALUES (?, ?, ?, ?, ?);', (
|
||||||
username,
|
username,
|
||||||
token,
|
token,
|
||||||
utils.GetTokenExpireOn(), # add 2 day from now
|
utils.GetTokenExpireOn(), # add 2 day from now
|
||||||
|
clientUa,
|
||||||
|
clientIp,
|
||||||
))
|
))
|
||||||
return token
|
return token
|
||||||
else:
|
else:
|
||||||
@@ -157,15 +159,17 @@ class CalendarDatabase(object):
|
|||||||
raise Exception('Login authentication failed')
|
raise Exception('Login authentication failed')
|
||||||
|
|
||||||
@SafeDatabaseOperation
|
@SafeDatabaseOperation
|
||||||
def common_webLogin(self, username, password):
|
def common_webLogin(self, username, password, clientUa, clientIp):
|
||||||
self.cursor.execute('SELECT [ccn_name] FROM user WHERE [ccn_name] = ? AND [ccn_password] = ?;', (username, utils.ComputePasswordHash(password)))
|
self.cursor.execute('SELECT [ccn_name] FROM user WHERE [ccn_name] = ? AND [ccn_password] = ?;', (username, utils.ComputePasswordHash(password)))
|
||||||
|
|
||||||
if len(self.cursor.fetchall()) != 0:
|
if len(self.cursor.fetchall()) != 0:
|
||||||
token = utils.GenerateToken(username)
|
token = utils.GenerateToken(username)
|
||||||
self.cursor.execute('INSERT INTO token VALUES (?, ?, ?);', (
|
self.cursor.execute('INSERT INTO token VALUES (?, ?, ?, ?, ?);', (
|
||||||
username,
|
username,
|
||||||
token,
|
token,
|
||||||
utils.GetTokenExpireOn(), # add 2 day from now
|
utils.GetTokenExpireOn(), # add 2 day from now
|
||||||
|
clientUa,
|
||||||
|
clientIp,
|
||||||
))
|
))
|
||||||
return token
|
return token
|
||||||
else:
|
else:
|
||||||
@@ -183,20 +187,6 @@ class CalendarDatabase(object):
|
|||||||
self.tokenOper_check_valid(token)
|
self.tokenOper_check_valid(token)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@SafeDatabaseOperation
|
|
||||||
def common_isAdmin(self, token):
|
|
||||||
username = self.tokenOper_get_username(token)
|
|
||||||
return self.tokenOper_is_admin(username)
|
|
||||||
|
|
||||||
@SafeDatabaseOperation
|
|
||||||
def common_changePassword(self, token, newpassword):
|
|
||||||
username = self.tokenOper_get_username(token)
|
|
||||||
self.cursor.execute('UPDATE user SET [ccn_password] = ? WHERE [ccn_name] = ?;', (
|
|
||||||
utils.ComputePasswordHash(newpassword),
|
|
||||||
username
|
|
||||||
))
|
|
||||||
return True
|
|
||||||
|
|
||||||
# =============================== calendar
|
# =============================== calendar
|
||||||
@SafeDatabaseOperation
|
@SafeDatabaseOperation
|
||||||
def calendar_getFull(self, token, startDateTime, endDateTime):
|
def calendar_getFull(self, token, startDateTime, endDateTime):
|
||||||
@@ -559,3 +549,40 @@ class CalendarDatabase(object):
|
|||||||
raise Exception('Fail to delete due to no matched rows or too much rows.')
|
raise Exception('Fail to delete due to no matched rows or too much rows.')
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
# =============================== profile
|
||||||
|
@SafeDatabaseOperation
|
||||||
|
def profile_isAdmin(self, token):
|
||||||
|
username = self.tokenOper_get_username(token)
|
||||||
|
return self.tokenOper_is_admin(username)
|
||||||
|
|
||||||
|
@SafeDatabaseOperation
|
||||||
|
def profile_changePassword(self, token, newpassword):
|
||||||
|
username = self.tokenOper_get_username(token)
|
||||||
|
self.cursor.execute('UPDATE user SET [ccn_password] = ? WHERE [ccn_name] = ?;', (
|
||||||
|
utils.ComputePasswordHash(newpassword),
|
||||||
|
username
|
||||||
|
))
|
||||||
|
return True
|
||||||
|
|
||||||
|
@SafeDatabaseOperation
|
||||||
|
def profile_getToken(self, token):
|
||||||
|
username = self.tokenOper_get_username(token)
|
||||||
|
|
||||||
|
self.cursor.execute('SELECT * FROM token WHERE [ccn_user] = ?;', (
|
||||||
|
username,
|
||||||
|
))
|
||||||
|
return self.cursor.fetchall()
|
||||||
|
|
||||||
|
@SafeDatabaseOperation
|
||||||
|
def profile_deleteToken(self, token, deleteToken):
|
||||||
|
_username = self.tokenOper_get_username(token)
|
||||||
|
|
||||||
|
# delete
|
||||||
|
self.cursor.execute('DELETE FROM token WHERE [ccn_user] = ? AND [ccn_token] = ?;', (
|
||||||
|
_username,
|
||||||
|
deleteToken
|
||||||
|
))
|
||||||
|
if self.cursor.rowcount != 1:
|
||||||
|
raise Exception('Fail to delete due to no matched rows or too much rows.')
|
||||||
|
return True
|
||||||
|
|
||||||
|
|||||||
169
src/server.py
169
src/server.py
@@ -92,40 +92,58 @@ def web_eventUpdateHandle(uuidPath):
|
|||||||
@app.route('/api/common/salt', methods=['POST'])
|
@app.route('/api/common/salt', methods=['POST'])
|
||||||
def api_common_saltHandle():
|
def api_common_saltHandle():
|
||||||
return SmartDbCaller(calendar_db.common_salt,
|
return SmartDbCaller(calendar_db.common_salt,
|
||||||
(('username', str, False), ))
|
(('username', str, False), ),
|
||||||
|
None)
|
||||||
|
|
||||||
@app.route('/api/common/login', methods=['POST'])
|
@app.route('/api/common/login', methods=['POST'])
|
||||||
def api_common_loginHandle():
|
def api_common_loginHandle():
|
||||||
|
# construct client data first
|
||||||
|
clientUa = request.user_agent.string
|
||||||
|
if request.headers.getlist("X-Forwarded-For"):
|
||||||
|
clientIp = request.headers.getlist("X-Forwarded-For")[0]
|
||||||
|
else:
|
||||||
|
clientIp = request.remote_addr
|
||||||
|
|
||||||
return SmartDbCaller(calendar_db.common_login,
|
return SmartDbCaller(calendar_db.common_login,
|
||||||
(('username', str, False),
|
(('username', str, False),
|
||||||
('password', str, False)))
|
('password', str, False),
|
||||||
|
('clientUa', str, False),
|
||||||
|
('clientIp', str, False)),
|
||||||
|
{
|
||||||
|
'clientUa': clientUa,
|
||||||
|
'clientIp': clientIp
|
||||||
|
})
|
||||||
|
|
||||||
@app.route('/api/common/webLogin', methods=['POST'])
|
@app.route('/api/common/webLogin', methods=['POST'])
|
||||||
def api_common_webLoginHandle():
|
def api_common_webLoginHandle():
|
||||||
|
# construct client data first
|
||||||
|
clientUa = request.user_agent.string
|
||||||
|
if request.headers.getlist("X-Forwarded-For"):
|
||||||
|
clientIp = request.headers.getlist("X-Forwarded-For")[0]
|
||||||
|
else:
|
||||||
|
clientIp = request.remote_addr
|
||||||
|
|
||||||
return SmartDbCaller(calendar_db.common_webLogin,
|
return SmartDbCaller(calendar_db.common_webLogin,
|
||||||
(('username', str, False),
|
(('username', str, False),
|
||||||
('password', str, False)))
|
('password', str, False),
|
||||||
|
('clientUa', str, False),
|
||||||
|
('clientIp', str, False)),
|
||||||
|
{
|
||||||
|
'clientUa': clientUa,
|
||||||
|
'clientIp': clientIp
|
||||||
|
})
|
||||||
|
|
||||||
@app.route('/api/common/logout', methods=['POST'])
|
@app.route('/api/common/logout', methods=['POST'])
|
||||||
def api_common_logoutHandle():
|
def api_common_logoutHandle():
|
||||||
return SmartDbCaller(calendar_db.common_logout,
|
return SmartDbCaller(calendar_db.common_logout,
|
||||||
(('token', str, False), ))
|
(('token', str, False), ),
|
||||||
|
None)
|
||||||
|
|
||||||
@app.route('/api/common/tokenValid', methods=['POST'])
|
@app.route('/api/common/tokenValid', methods=['POST'])
|
||||||
def api_common_tokenValidHandle():
|
def api_common_tokenValidHandle():
|
||||||
return SmartDbCaller(calendar_db.common_tokenValid,
|
return SmartDbCaller(calendar_db.common_tokenValid,
|
||||||
(('token', str, False), ))
|
(('token', str, False), ),
|
||||||
|
None)
|
||||||
@app.route('/api/common/isAdmin', methods=['POST'])
|
|
||||||
def api_common_isAdminHandle():
|
|
||||||
return SmartDbCaller(calendar_db.common_isAdmin,
|
|
||||||
(('token', str, False), ))
|
|
||||||
|
|
||||||
@app.route('/api/common/changePassword', methods=['POST'])
|
|
||||||
def api_common_changePasswordHandle():
|
|
||||||
return SmartDbCaller(calendar_db.common_changePassword,
|
|
||||||
(('token', str, False),
|
|
||||||
('password', str, False)))
|
|
||||||
|
|
||||||
# ================================ calendar
|
# ================================ calendar
|
||||||
|
|
||||||
@@ -134,20 +152,23 @@ def api_calendar_getFullHandle():
|
|||||||
return SmartDbCaller(calendar_db.calendar_getFull,
|
return SmartDbCaller(calendar_db.calendar_getFull,
|
||||||
(('token', str, False),
|
(('token', str, False),
|
||||||
('startDateTime', int, False),
|
('startDateTime', int, False),
|
||||||
('endDateTime', int, False)))
|
('endDateTime', int, False)),
|
||||||
|
None)
|
||||||
|
|
||||||
@app.route('/api/calendar/getList', methods=['POST'])
|
@app.route('/api/calendar/getList', methods=['POST'])
|
||||||
def api_calendar_getListHandle():
|
def api_calendar_getListHandle():
|
||||||
return SmartDbCaller(calendar_db.calendar_getList,
|
return SmartDbCaller(calendar_db.calendar_getList,
|
||||||
(('token', str, False),
|
(('token', str, False),
|
||||||
('startDateTime', int, False),
|
('startDateTime', int, False),
|
||||||
('endDateTime', int, False)))
|
('endDateTime', int, False)),
|
||||||
|
None)
|
||||||
|
|
||||||
@app.route('/api/calendar/getDetail', methods=['POST'])
|
@app.route('/api/calendar/getDetail', methods=['POST'])
|
||||||
def api_calendar_getDetailHandle():
|
def api_calendar_getDetailHandle():
|
||||||
return SmartDbCaller(calendar_db.calendar_getDetail,
|
return SmartDbCaller(calendar_db.calendar_getDetail,
|
||||||
(('token', str, False),
|
(('token', str, False),
|
||||||
('uuid', str, False)))
|
('uuid', str, False)),
|
||||||
|
None)
|
||||||
|
|
||||||
@app.route('/api/calendar/update', methods=['POST'])
|
@app.route('/api/calendar/update', methods=['POST'])
|
||||||
def api_calendar_updateHandle():
|
def api_calendar_updateHandle():
|
||||||
@@ -161,7 +182,8 @@ def api_calendar_updateHandle():
|
|||||||
('eventDateTimeEnd', int, True),
|
('eventDateTimeEnd', int, True),
|
||||||
('loopRules', str, True),
|
('loopRules', str, True),
|
||||||
('timezoneOffset', int, True),
|
('timezoneOffset', int, True),
|
||||||
('lastChange', str, False)))
|
('lastChange', str, False)),
|
||||||
|
None)
|
||||||
|
|
||||||
@app.route('/api/calendar/add', methods=['POST'])
|
@app.route('/api/calendar/add', methods=['POST'])
|
||||||
def api_calendar_addHandle():
|
def api_calendar_addHandle():
|
||||||
@@ -173,38 +195,44 @@ def api_calendar_addHandle():
|
|||||||
('eventDateTimeStart', int, False),
|
('eventDateTimeStart', int, False),
|
||||||
('eventDateTimeEnd', int, False),
|
('eventDateTimeEnd', int, False),
|
||||||
('loopRules', str, False),
|
('loopRules', str, False),
|
||||||
('timezoneOffset', int, False)))
|
('timezoneOffset', int, False)),
|
||||||
|
None)
|
||||||
|
|
||||||
@app.route('/api/calendar/delete', methods=['POST'])
|
@app.route('/api/calendar/delete', methods=['POST'])
|
||||||
def api_calendar_deleteHandle():
|
def api_calendar_deleteHandle():
|
||||||
return SmartDbCaller(calendar_db.calendar_delete,
|
return SmartDbCaller(calendar_db.calendar_delete,
|
||||||
(('token', str, False),
|
(('token', str, False),
|
||||||
('uuid', str, False),
|
('uuid', str, False),
|
||||||
('lastChange', str, False)))
|
('lastChange', str, False)),
|
||||||
|
None)
|
||||||
|
|
||||||
# ================================ collection
|
# ================================ collection
|
||||||
|
|
||||||
@app.route('/api/collection/getFullOwn', methods=['POST'])
|
@app.route('/api/collection/getFullOwn', methods=['POST'])
|
||||||
def api_collection_getFullOwnHandle():
|
def api_collection_getFullOwnHandle():
|
||||||
return SmartDbCaller(calendar_db.collection_getFullOwn,
|
return SmartDbCaller(calendar_db.collection_getFullOwn,
|
||||||
(('token', str, False), ))
|
(('token', str, False), ),
|
||||||
|
None)
|
||||||
|
|
||||||
@app.route('/api/collection/getListOwn', methods=['POST'])
|
@app.route('/api/collection/getListOwn', methods=['POST'])
|
||||||
def api_collection_getListOwnHandle():
|
def api_collection_getListOwnHandle():
|
||||||
return SmartDbCaller(calendar_db.collection_getListlOwn,
|
return SmartDbCaller(calendar_db.collection_getListlOwn,
|
||||||
(('token', str, False), ))
|
(('token', str, False), ),
|
||||||
|
None)
|
||||||
|
|
||||||
@app.route('/api/collection/getDetailOwn', methods=['POST'])
|
@app.route('/api/collection/getDetailOwn', methods=['POST'])
|
||||||
def api_collection_getDetailOwnHandle():
|
def api_collection_getDetailOwnHandle():
|
||||||
return SmartDbCaller(calendar_db.collection_getDetailOwn,
|
return SmartDbCaller(calendar_db.collection_getDetailOwn,
|
||||||
(('token', str, False),
|
(('token', str, False),
|
||||||
('uuid', str, False)))
|
('uuid', str, False)),
|
||||||
|
None)
|
||||||
|
|
||||||
@app.route('/api/collection/addOwn', methods=['POST'])
|
@app.route('/api/collection/addOwn', methods=['POST'])
|
||||||
def api_collection_addOwnHandle():
|
def api_collection_addOwnHandle():
|
||||||
return SmartDbCaller(calendar_db.collection_addOwn,
|
return SmartDbCaller(calendar_db.collection_addOwn,
|
||||||
(('token', str, False),
|
(('token', str, False),
|
||||||
('name', str, False)))
|
('name', str, False)),
|
||||||
|
None)
|
||||||
|
|
||||||
@app.route('/api/collection/updateOwn', methods=['POST'])
|
@app.route('/api/collection/updateOwn', methods=['POST'])
|
||||||
def api_collection_updateOwnHandle():
|
def api_collection_updateOwnHandle():
|
||||||
@@ -212,21 +240,24 @@ def api_collection_updateOwnHandle():
|
|||||||
(('token', str, False),
|
(('token', str, False),
|
||||||
('uuid', str, False),
|
('uuid', str, False),
|
||||||
('name', str, False),
|
('name', str, False),
|
||||||
('lastChange', str, False)))
|
('lastChange', str, False)),
|
||||||
|
None)
|
||||||
|
|
||||||
@app.route('/api/collection/deleteOwn', methods=['POST'])
|
@app.route('/api/collection/deleteOwn', methods=['POST'])
|
||||||
def api_collection_deleteOwnHandle():
|
def api_collection_deleteOwnHandle():
|
||||||
return SmartDbCaller(calendar_db.collection_deleteOwn,
|
return SmartDbCaller(calendar_db.collection_deleteOwn,
|
||||||
(('token', str, False),
|
(('token', str, False),
|
||||||
('uuid', str, False),
|
('uuid', str, False),
|
||||||
('lastChange', str, False)))
|
('lastChange', str, False)),
|
||||||
|
None)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/api/collection/getSharing', methods=['POST'])
|
@app.route('/api/collection/getSharing', methods=['POST'])
|
||||||
def api_collection_getSharingHandle():
|
def api_collection_getSharingHandle():
|
||||||
return SmartDbCaller(calendar_db.collection_getSharing,
|
return SmartDbCaller(calendar_db.collection_getSharing,
|
||||||
(('token', str, False),
|
(('token', str, False),
|
||||||
('uuid', str, False)))
|
('uuid', str, False)),
|
||||||
|
None)
|
||||||
|
|
||||||
@app.route('/api/collection/deleteSharing', methods=['POST'])
|
@app.route('/api/collection/deleteSharing', methods=['POST'])
|
||||||
def api_collection_deleteSharingHandle():
|
def api_collection_deleteSharingHandle():
|
||||||
@@ -234,7 +265,8 @@ def api_collection_deleteSharingHandle():
|
|||||||
(('token', str, False),
|
(('token', str, False),
|
||||||
('uuid', str, False),
|
('uuid', str, False),
|
||||||
('target', str, False),
|
('target', str, False),
|
||||||
('lastChange', str, False)))
|
('lastChange', str, False)),
|
||||||
|
None)
|
||||||
|
|
||||||
@app.route('/api/collection/addSharing', methods=['POST'])
|
@app.route('/api/collection/addSharing', methods=['POST'])
|
||||||
def api_collection_addSharingHandle():
|
def api_collection_addSharingHandle():
|
||||||
@@ -242,37 +274,42 @@ def api_collection_addSharingHandle():
|
|||||||
(('token', str, False),
|
(('token', str, False),
|
||||||
('uuid', str, False),
|
('uuid', str, False),
|
||||||
('target', str, False),
|
('target', str, False),
|
||||||
('lastChange', str, False)))
|
('lastChange', str, False)),
|
||||||
|
None)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/api/collection/getShared', methods=['POST'])
|
@app.route('/api/collection/getShared', methods=['POST'])
|
||||||
def api_collection_getSharedHandle():
|
def api_collection_getSharedHandle():
|
||||||
return SmartDbCaller(calendar_db.collection_getShared,
|
return SmartDbCaller(calendar_db.collection_getShared,
|
||||||
(('token', str, False), ))
|
(('token', str, False), ),
|
||||||
|
None)
|
||||||
|
|
||||||
# ================================ todo
|
# ================================ todo
|
||||||
|
|
||||||
@app.route('/api/todo/getFull', methods=['POST'])
|
@app.route('/api/todo/getFull', methods=['POST'])
|
||||||
def api_todo_getFullHandle():
|
def api_todo_getFullHandle():
|
||||||
return SmartDbCaller(calendar_db.todo_getFull,
|
return SmartDbCaller(calendar_db.todo_getFull,
|
||||||
(('token', str, False), ))
|
(('token', str, False), ),
|
||||||
|
None)
|
||||||
|
|
||||||
@app.route('/api/todo/getList', methods=['POST'])
|
@app.route('/api/todo/getList', methods=['POST'])
|
||||||
def api_todo_getListHandle():
|
def api_todo_getListHandle():
|
||||||
return SmartDbCaller(calendar_db.todo_getList,
|
return SmartDbCaller(calendar_db.todo_getList,
|
||||||
(('token', str, False), ))
|
(('token', str, False), ),
|
||||||
|
None)
|
||||||
|
|
||||||
@app.route('/api/todo/getDetail', methods=['POST'])
|
@app.route('/api/todo/getDetail', methods=['POST'])
|
||||||
def api_todo_getDetailHandle():
|
def api_todo_getDetailHandle():
|
||||||
return SmartDbCaller(calendar_db.todo_getDetail,
|
return SmartDbCaller(calendar_db.todo_getDetail,
|
||||||
(('token', str, False),
|
(('token', str, False),
|
||||||
('uuid', str, False)))
|
('uuid', str, False)),
|
||||||
|
None)
|
||||||
|
|
||||||
@app.route('/api/todo/add', methods=['POST'])
|
@app.route('/api/todo/add', methods=['POST'])
|
||||||
def api_todo_addHandle():
|
def api_todo_addHandle():
|
||||||
return SmartDbCaller(calendar_db.todo_add,
|
return SmartDbCaller(calendar_db.todo_add,
|
||||||
(('token', str, False), ))
|
(('token', str, False), ),
|
||||||
|
None)
|
||||||
|
|
||||||
@app.route('/api/todo/update', methods=['POST'])
|
@app.route('/api/todo/update', methods=['POST'])
|
||||||
def api_todo_updateHandle():
|
def api_todo_updateHandle():
|
||||||
@@ -280,27 +317,31 @@ def api_todo_updateHandle():
|
|||||||
(('token', str, False),
|
(('token', str, False),
|
||||||
('uuid', str, False),
|
('uuid', str, False),
|
||||||
('data', str, False),
|
('data', str, False),
|
||||||
('lastChange', str, False)))
|
('lastChange', str, False)),
|
||||||
|
None)
|
||||||
|
|
||||||
@app.route('/api/todo/delete', methods=['POST'])
|
@app.route('/api/todo/delete', methods=['POST'])
|
||||||
def api_todo_deleteHandle():
|
def api_todo_deleteHandle():
|
||||||
return SmartDbCaller(calendar_db.todo_delete,
|
return SmartDbCaller(calendar_db.todo_delete,
|
||||||
(('token', str, False),
|
(('token', str, False),
|
||||||
('uuid', str, False),
|
('uuid', str, False),
|
||||||
('lastChange', str, False)))
|
('lastChange', str, False)),
|
||||||
|
None)
|
||||||
|
|
||||||
# ================================ admin
|
# ================================ admin
|
||||||
|
|
||||||
@app.route('/api/admin/get', methods=['POST'])
|
@app.route('/api/admin/get', methods=['POST'])
|
||||||
def api_admin_getHandle():
|
def api_admin_getHandle():
|
||||||
return SmartDbCaller(calendar_db.admin_get,
|
return SmartDbCaller(calendar_db.admin_get,
|
||||||
(('token', str, False), ))
|
(('token', str, False), ),
|
||||||
|
None)
|
||||||
|
|
||||||
@app.route('/api/admin/add', methods=['POST'])
|
@app.route('/api/admin/add', methods=['POST'])
|
||||||
def api_admin_addHandle():
|
def api_admin_addHandle():
|
||||||
return SmartDbCaller(calendar_db.admin_add,
|
return SmartDbCaller(calendar_db.admin_add,
|
||||||
(('token', str, False),
|
(('token', str, False),
|
||||||
('username', str, False)))
|
('username', str, False)),
|
||||||
|
None)
|
||||||
|
|
||||||
@app.route('/api/admin/update', methods=['POST'])
|
@app.route('/api/admin/update', methods=['POST'])
|
||||||
def api_admin_updateHandle():
|
def api_admin_updateHandle():
|
||||||
@@ -308,13 +349,43 @@ def api_admin_updateHandle():
|
|||||||
(('token', str, False),
|
(('token', str, False),
|
||||||
('username', str, False),
|
('username', str, False),
|
||||||
('password', str, True),
|
('password', str, True),
|
||||||
('isAdmin', utils.Str2Bool, True)))
|
('isAdmin', utils.Str2Bool, True)),
|
||||||
|
None)
|
||||||
|
|
||||||
@app.route('/api/admin/delete', methods=['POST'])
|
@app.route('/api/admin/delete', methods=['POST'])
|
||||||
def api_admin_deleteHandle():
|
def api_admin_deleteHandle():
|
||||||
return SmartDbCaller(calendar_db.admin_delete,
|
return SmartDbCaller(calendar_db.admin_delete,
|
||||||
(('token', str, False),
|
(('token', str, False),
|
||||||
('username', str, False)))
|
('username', str, False)),
|
||||||
|
None)
|
||||||
|
|
||||||
|
# ================================ profile
|
||||||
|
|
||||||
|
@app.route('/api/profile/isAdmin', methods=['POST'])
|
||||||
|
def api_profile_isAdminHandle():
|
||||||
|
return SmartDbCaller(calendar_db.profile_isAdmin,
|
||||||
|
(('token', str, False), ),
|
||||||
|
None)
|
||||||
|
|
||||||
|
@app.route('/api/profile/changePassword', methods=['POST'])
|
||||||
|
def api_profile_changePasswordHandle():
|
||||||
|
return SmartDbCaller(calendar_db.profile_changePassword,
|
||||||
|
(('token', str, False),
|
||||||
|
('password', str, False)),
|
||||||
|
None)
|
||||||
|
|
||||||
|
@app.route('/api/profile/getToken', methods=['POST'])
|
||||||
|
def api_profile_getTokenHandle():
|
||||||
|
return SmartDbCaller(calendar_db.profile_getToken,
|
||||||
|
(('token', str, False), ),
|
||||||
|
None)
|
||||||
|
|
||||||
|
@app.route('/api/profile/deleteToken', methods=['POST'])
|
||||||
|
def api_profile_deleteTokenHandle():
|
||||||
|
return SmartDbCaller(calendar_db.profile_deleteToken,
|
||||||
|
(('token', str, False),
|
||||||
|
('deleteToken', str, False)),
|
||||||
|
None)
|
||||||
|
|
||||||
# =============================================main run
|
# =============================================main run
|
||||||
|
|
||||||
@@ -336,14 +407,20 @@ def UpdateStaticResources():
|
|||||||
}
|
}
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def SmartDbCaller(dbMethod, paramTuple):
|
def SmartDbCaller(dbMethod, paramTuple, extraDict):
|
||||||
result = (False, 'Invalid parameter', None)
|
result = (False, 'Invalid parameter', None)
|
||||||
optCount = 0
|
optCount = 0
|
||||||
paramList = []
|
paramList = []
|
||||||
optParamDict = {}
|
optParamDict = {}
|
||||||
# for each item, item[0] is field name. item[1] is type. item[2] is whether it is optional field
|
# for each item,
|
||||||
|
# item[0] is field name.
|
||||||
|
# item[1] is type.
|
||||||
|
# item[2] is whether it is optional field
|
||||||
|
realForm = request.form.to_dict()
|
||||||
|
if extraDict is not None:
|
||||||
|
realForm.update(extraDict)
|
||||||
for item in paramTuple:
|
for item in paramTuple:
|
||||||
cache = request.form.get(item[0], default=None, type=item[1])
|
cache = item[1](realForm.get(item[0], None))
|
||||||
if item[2]:
|
if item[2]:
|
||||||
# optional param
|
# optional param
|
||||||
if cache is not None:
|
if cache is not None:
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ CREATE TABLE token(
|
|||||||
[ccn_user] TEXT NOT NULL,
|
[ccn_user] TEXT NOT NULL,
|
||||||
[ccn_token] TEXT UNIQUE NOT NULL,
|
[ccn_token] TEXT UNIQUE NOT NULL,
|
||||||
[ccn_tokenExpireOn] BIGINT NOT NULL,
|
[ccn_tokenExpireOn] BIGINT NOT NULL,
|
||||||
|
[ccn_ua] TEXT NOT NULL,
|
||||||
|
[ccn_ip] TEXT NOT NULL,
|
||||||
|
|
||||||
FOREIGN KEY (ccn_user) REFERENCES user(ccn_name) ON DELETE CASCADE
|
FOREIGN KEY (ccn_user) REFERENCES user(ccn_name) ON DELETE CASCADE
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -24,6 +24,31 @@ div.user-item-icon {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
div.token-item {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: row;
|
||||||
|
align-items: flex-start;
|
||||||
|
|
||||||
|
padding: 1.25rem;
|
||||||
|
margin-bottom: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.token-item-words {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
flex-grow: 1;
|
||||||
|
flex-basis: 0;
|
||||||
|
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.token-item-icon {
|
||||||
|
margin-left: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
div.control-list {
|
div.control-list {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@@ -134,4 +134,5 @@ ccn-i18n-userItem-isAdmin=Is Admin
|
|||||||
|
|
||||||
ccn-i18n-tokenItem-ua=User Agent:
|
ccn-i18n-tokenItem-ua=User Agent:
|
||||||
ccn-i18n-tokenItem-ip=IP:
|
ccn-i18n-tokenItem-ip=IP:
|
||||||
|
ccn-i18n-tokenItem-expireOn=Expire On:
|
||||||
ccn-i18n-tokenItem-isMe=This is the login credentials you are currently using.
|
ccn-i18n-tokenItem-isMe=This is the login credentials you are currently using.
|
||||||
|
|||||||
@@ -134,4 +134,5 @@ ccn-i18n-userItem-isAdmin=是管理员
|
|||||||
|
|
||||||
ccn-i18n-tokenItem-ua=UA:
|
ccn-i18n-tokenItem-ua=UA:
|
||||||
ccn-i18n-tokenItem-ip=IP:
|
ccn-i18n-tokenItem-ip=IP:
|
||||||
|
ccn-i18n-tokenItem-expireOn=过期时间:
|
||||||
ccn-i18n-tokenItem-isMe=这是你当前使用的登录凭据
|
ccn-i18n-tokenItem-isMe=这是你当前使用的登录凭据
|
||||||
|
|||||||
@@ -179,25 +179,6 @@ function ccn_api_common_tokenValid() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function ccn_api_common_isAdmin() {
|
|
||||||
return ccn_api_boolTemplate(
|
|
||||||
'/api/common/isAdmin',
|
|
||||||
{
|
|
||||||
token: ccn_localstorageAssist_GetApiToken()
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function ccn_api_common_changePassword(_password) {
|
|
||||||
return ccn_api_boolTemplate(
|
|
||||||
'/api/common/changePassword',
|
|
||||||
{
|
|
||||||
token: ccn_localstorageAssist_GetApiToken(),
|
|
||||||
password: _password
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ====================================================== calendar
|
// ====================================================== calendar
|
||||||
|
|
||||||
function ccn_api_calendar_getFull(_startDateTime, _endDateTime) {
|
function ccn_api_calendar_getFull(_startDateTime, _endDateTime) {
|
||||||
@@ -461,3 +442,42 @@ function ccn_api_admin_delete(_username) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ====================================================== profile
|
||||||
|
|
||||||
|
function ccn_api_profile_isAdmin() {
|
||||||
|
return ccn_api_boolTemplate(
|
||||||
|
'/api/profile/isAdmin',
|
||||||
|
{
|
||||||
|
token: ccn_localstorageAssist_GetApiToken()
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ccn_api_profile_changePassword(_password) {
|
||||||
|
return ccn_api_boolTemplate(
|
||||||
|
'/api/profile/changePassword',
|
||||||
|
{
|
||||||
|
token: ccn_localstorageAssist_GetApiToken(),
|
||||||
|
password: _password
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ccn_api_profile_getToken() {
|
||||||
|
return ccn_api_boolTemplate(
|
||||||
|
'/api/profile/getToken',
|
||||||
|
{
|
||||||
|
token: ccn_localstorageAssist_GetApiToken()
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ccn_api_profile_deleteToken(_deleteToken) {
|
||||||
|
return ccn_api_boolTemplate(
|
||||||
|
'/api/profile/deleteToken',
|
||||||
|
{
|
||||||
|
token: ccn_localstorageAssist_GetApiToken(),
|
||||||
|
deleteToken: _deleteToken
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
var ccn_admin_userListCache = [];
|
var ccn_admin_userListCache = [];
|
||||||
|
var ccn_admin_tokenListCache = [];
|
||||||
|
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
ccn_pages_currentPage = ccn_pages_enumPages.admin;
|
ccn_pages_currentPage = ccn_pages_enumPages.admin;
|
||||||
@@ -28,7 +29,7 @@ $(document).ready(function() {
|
|||||||
ccn_tabcontrol_SwitchTab(1, 1);
|
ccn_tabcontrol_SwitchTab(1, 1);
|
||||||
|
|
||||||
// load user tab according to admin status
|
// load user tab according to admin status
|
||||||
if(!ccn_api_common_isAdmin())
|
if(!ccn_api_profile_isAdmin())
|
||||||
$('#tabcontrol-tab-1-3').hide();
|
$('#tabcontrol-tab-1-3').hide();
|
||||||
|
|
||||||
// apply i18n
|
// apply i18n
|
||||||
@@ -37,6 +38,7 @@ $(document).ready(function() {
|
|||||||
|
|
||||||
// bind event
|
// bind event
|
||||||
$('#ccn-admin-profile-btnChangePassword').click(ccn_admin_profile_ChangePassword);
|
$('#ccn-admin-profile-btnChangePassword').click(ccn_admin_profile_ChangePassword);
|
||||||
|
$('#ccn-admin-tokenList-btnRefresh').click(ccn_admin_tokenList_Refresh);
|
||||||
$('#ccn-admin-userList-btnAdd').click(ccn_admin_userList_Add);
|
$('#ccn-admin-userList-btnAdd').click(ccn_admin_userList_Add);
|
||||||
$('#ccn-admin-userList-btnRefresh').click(ccn_admin_userList_Refresh);
|
$('#ccn-admin-userList-btnRefresh').click(ccn_admin_userList_Refresh);
|
||||||
});
|
});
|
||||||
@@ -47,7 +49,7 @@ function ccn_admin_profile_ChangePassword() {
|
|||||||
var newpassword = $('#ccn-admin-profile-inputPassword').val();
|
var newpassword = $('#ccn-admin-profile-inputPassword').val();
|
||||||
if (newpassword == "") return;
|
if (newpassword == "") return;
|
||||||
|
|
||||||
var result = ccn_api_common_changePassword(newpassword);
|
var result = ccn_api_profile_changePassword(newpassword);
|
||||||
if(result) {
|
if(result) {
|
||||||
ccn_messagebox_Show($.i18n.prop("ccn-i18n-js-success"));
|
ccn_messagebox_Show($.i18n.prop("ccn-i18n-js-success"));
|
||||||
$('#ccn-admin-profile-inputPassword').val('');
|
$('#ccn-admin-profile-inputPassword').val('');
|
||||||
@@ -56,6 +58,61 @@ function ccn_admin_profile_ChangePassword() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ================== token
|
||||||
|
|
||||||
|
function ccn_admin_tokenList_Refresh() {
|
||||||
|
ccn_admin_tokenListCache = new Array();
|
||||||
|
var listDOM = $('#ccn-admin-tokenList');
|
||||||
|
listDOM.empty();
|
||||||
|
|
||||||
|
var renderdata = {
|
||||||
|
uuid: undefined,
|
||||||
|
isMe: undefined,
|
||||||
|
ua: undefined,
|
||||||
|
ip: undefined,
|
||||||
|
expireOn: undefined
|
||||||
|
}
|
||||||
|
var gottenDateTime = new Date();
|
||||||
|
|
||||||
|
var result = ccn_api_profile_getToken();
|
||||||
|
if(typeof(result) != 'undefined') {
|
||||||
|
for(var index in result) {
|
||||||
|
var item = result[index];
|
||||||
|
renderdata.uuid = item[1];
|
||||||
|
renderdata.isMe = ccn_localstorageAssist_GetApiToken() == item[1];
|
||||||
|
renderdata.ua = item[3];
|
||||||
|
renderdata.ip = item[4];
|
||||||
|
gottenDateTime.setTime(item[2] * 1000);
|
||||||
|
renderdata.expireOn = gottenDateTime.toLocaleString();
|
||||||
|
|
||||||
|
listDOM.append(ccn_template_tokenItem.render(renderdata));
|
||||||
|
|
||||||
|
// bind event
|
||||||
|
var uuid = renderdata.uuid;
|
||||||
|
$("#ccn-tokenItem-btnLogout-" + uuid).click(ccn_admin_tokenList_ItemDelete);
|
||||||
|
|
||||||
|
// add into cache
|
||||||
|
ccn_admin_tokenListCache[uuid] = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
ccn_i18n_ApplyLanguage2Content(listDOM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function ccn_admin_tokenList_ItemDelete() {
|
||||||
|
var uuid = $(this).attr("uuid");
|
||||||
|
|
||||||
|
var result = ccn_api_profile_deleteToken(uuid);
|
||||||
|
|
||||||
|
if(!result) {
|
||||||
|
// fail
|
||||||
|
ccn_messagebox_Show($.i18n.prop("ccn-i18n-js-fail-delete"));
|
||||||
|
} else {
|
||||||
|
// remove body
|
||||||
|
$("#ccn-tokenItem-" + uuid).remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ================== user list
|
// ================== user list
|
||||||
|
|
||||||
function ccn_admin_userList_RefreshCacheList() {
|
function ccn_admin_userList_RefreshCacheList() {
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
<div id="ccn-tokenItem-{{:uuid}}" class="token-item card">
|
<div id="ccn-tokenItem-{{:uuid}}" class="token-item card">
|
||||||
<div class="token-item-words">
|
<div class="token-item-words">
|
||||||
<b>{{>token}}</b>
|
<b>{{>uuid}}</b>
|
||||||
{{if isMe}}
|
|
||||||
<p i18n-name="ccn-i18n-tokenItem-isMe"></p>
|
|
||||||
{{/if}}
|
|
||||||
<p>
|
<p>
|
||||||
<span i18n-name="ccn-i18n-tokenItem-ua"></span>
|
<span i18n-name="ccn-i18n-tokenItem-ua"></span>
|
||||||
<span>{{>ua}}</span>
|
<span>{{>ua}}</span>
|
||||||
@@ -12,6 +9,16 @@
|
|||||||
<span i18n-name="ccn-i18n-tokenItem-ip"></span>
|
<span i18n-name="ccn-i18n-tokenItem-ip"></span>
|
||||||
<span>{{>ip}}</span>
|
<span>{{>ip}}</span>
|
||||||
</p>
|
</p>
|
||||||
|
<p>
|
||||||
|
<span i18n-name="ccn-i18n-tokenItem-expireOn"></span>
|
||||||
|
<span>{{>expireOn}}</span>
|
||||||
|
</p>
|
||||||
|
{{if isMe}}
|
||||||
|
<p>
|
||||||
|
<span class="icon is-small"><i class="fas fa-exclamation-triangle"></i></span>
|
||||||
|
<span i18n-name="ccn-i18n-tokenItem-isMe"></span>
|
||||||
|
</p>
|
||||||
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="ccn-tokenItem-btnLogout-{{:uuid}}" uuid="{{:uuid}}" class="token-item-icon control">
|
<div id="ccn-tokenItem-btnLogout-{{:uuid}}" uuid="{{:uuid}}" class="token-item-icon control">
|
||||||
|
|||||||
Reference in New Issue
Block a user