From 25f22064aa65978a5ec0b71941be50e8a9790b3b Mon Sep 17 00:00:00 2001 From: yyc12345 Date: Tue, 2 Feb 2021 12:11:13 +0800 Subject: [PATCH] nightly commit --- documents/Principle_zh-CN.md | 11 +-- src/database.py | 127 ++++++++++++++++++++++++++++++++--- src/server.py | 7 +- src/sql/sqlite.sql | 1 + 4 files changed, 132 insertions(+), 14 deletions(-) diff --git a/documents/Principle_zh-CN.md b/documents/Principle_zh-CN.md index 408c06e..869fe03 100644 --- a/documents/Principle_zh-CN.md +++ b/documents/Principle_zh-CN.md @@ -35,6 +35,7 @@ CREATE TABLE calendar( [ccn_eventDateTimeStart] BIGINT NOT NULL, [ccn_eventDateTimeEnd] BIGINT NOT NULL, + [ccn_timezoneOffset] INT NOT NULL, [ccn_loopRules] TEXT NOT NULL, [ccn_loopDateTimeStart] BIGINT NOT NULL, @@ -49,6 +50,8 @@ CREATE TABLE calendar( `ccn_eventDateTimeStart`和`ccn_eventDateTimeEnd`,分别表示开始时间和结束时间。如果是循环事件,则表示此循环事件的第一个事件发生的时间。对于常用的点事件,或者全天事件,归于前者情况里面,通过设定开始和结束时间为一分钟和全天来解决。 +`ccn_timezoneOffset`是客户端指定的对`ccn_eventDateTimeStart`和`ccn_eventDateTimeEnd`时区设定,这个值是传递给客户端和服务端本身进行计算用的。在服务器,2个事件时间仍然是UNIX时间戳。 + `ccn_loopRules`是事件循环的规则,其格式详见后文的事件循环规则字符串章节。 `ccn_loopDateTimeStart`和`ccn_loopDateTimeEnd`是事件循环的时间,同时也被用于检索符合条件的事件返回给客户端。因此,对于非循环事件,其数值与`ccn_eventDateTimeStart`和`ccn_eventDateTimeEnd`保持一致。对于循环事件,则表示循环事件的循环的开始和结束时间。通常来说,`ccn_loopDateTimeStart`和`ccn_eventDateTimeStart`是一样的,无论是循环还是非循环事件。循环结束时间有3种类型,如果是无限循环,则将结束时间设置为Int64最大值。如果是指定时间,则设置成指定时间当天的最后一秒。如果是指定次数,则由算法算出最后时间。 @@ -239,12 +242,12 @@ Calendar类下的为日历请求接口 |eventDateTimeStart|int|事件开始时间| |eventDateTimeEnd|int|事件结束时间| |loopRules|string|事件循环规则| -|timezoneOffset|int|提交请求的用户的本地时间与UTC时间之间的差值,使用本程序指定的粒度为分钟的时间差| +|timezoneOffset|int|此事件的本地时间与UTC时间之间的差值,使用本程序指定的粒度为分钟的时间差| |lastChange|string|用于同步验证| 返回参数:新的lastChange,用以更新本地缓存 -除去token,uuid,timezoneOffset和lastChange这4项用来鉴别的条目外,其余的条目均为可选项,提供则更新,不提供则不更新。 +除去token,uuid和lastChange这3项用来鉴别的条目外,其余的条目均为可选项,提供则更新,不提供则不更新。 #### add @@ -261,7 +264,7 @@ Calendar类下的为日历请求接口 |eventDateTimeStart|int|事件开始时间| |eventDateTimeEnd|int|事件结束时间| |loopRules|string|事件循环规则| -|timezoneOffset|int|提交请求的用户的本地时间与UTC时间之间的差值,使用本程序指定的粒度为分钟的时间差| +|timezoneOffset|int|此事件的本地时间与UTC时间之间的差值,使用本程序指定的粒度为分钟的时间差| 返回参数:新事件的uuid,用以本地更新 @@ -321,7 +324,7 @@ Collection类下的为日历集合请求接口 |token|string|用于用户鉴权的字符串| |uuid|string|需要获取集合的uuid| -返回参数:一个json,返回collection数据表中对应uuid的条目 +返回参数:一个json,返回collection数据表中对应uuid的条目。没有符合条件的则返回null。 #### addOwn diff --git a/src/database.py b/src/database.py index f5d827f..fa42913 100644 --- a/src/database.py +++ b/src/database.py @@ -195,7 +195,125 @@ class CalendarDatabase(object): return True # =============================== calendar + @SafeDatabaseOperation + def calendar_getFull(self, token, startDateTime, endDateTime): + username = self.tokenOper_get_username(token) + self.cursor.execute('SELECT calendar.* FROM calendar INNER JOIN collection \ + ON collection.ccn_uuid = calendar.ccn_belongTo \ + WHERE (collection.ccn_user = ? AND calendar.ccn_loopDateTimeEnd >= ? AND calendar.ccn_loopDateTimeStart <= ?);', + (username, startDateTime, endDateTime)) + return self.cursor.fetchall() + @SafeDatabaseOperation + def calendar_getList(self, token, startDateTime, endDateTime): + username = self.tokenOper_get_username(token) + self.cursor.execute('SELECT calendar.ccn_uuid FROM calendar INNER JOIN collection \ + ON collection.ccn_uuid = calendar.ccn_belongTo \ + WHERE (collection.ccn_user = ? AND calendar.ccn_loopDateTimeEnd >= ? AND calendar.ccn_loopDateTimeStart <= ?);', + (username, startDateTime, endDateTime)) + return tuple(map(lambda x: x[0], self.cursor.fetchall())) + + @SafeDatabaseOperation + def calendar_getDetail(self, token, uuid): + self.tokenOper_check_valid(token) + self.cursor.execute('SELECT * FROM calendar WHERE [ccn_uuid] = ?;', (uuid, )) + return self.cursor.fetchone() + + @SafeDatabaseOperation + def calendar_update(self, token, uuid, lastChange, **optArgs): + self.tokenOper_check_valid(token) + + # get prev data + self.cursor.execute('SELECT * FROM calendar WHERE [ccn_uuid] = ? AND [ccn_lastChange] = ?;', (uuid, lastChange)) + analyseData = self.cursor.fetchone() + + # construct update data + lastupdate = utils.GenerateUUID() + sqlList = [ + '[ccn_lastChange] = ?', + ] + argumentsList = [ + lastupdate, + ] + + # analyse opt arg + reAnalyseLoop = False + + cache = optArgs.get('belongTo', default=None) + if cache is not None: + sqlList.append('[ccn_belongTo] = ?') + argumentsList.append(cache) + cache = optArgs.get('title', default=None) + if cache is not None: + sqlList.append('[ccn_title] = ?') + argumentsList.append(cache) + cache = optArgs.get('description', default=None) + if cache is not None: + sqlList.append('[ccn_description] = ?') + argumentsList.append(cache) + cache = optArgs.get('eventDateTimeStart', default=None) + if cache is not None: + sqlList.append('[ccn_eventDateTimeStart] = ?') + argumentsList.append(cache) + reAnalyseLoop = True + analyseData[5] = cache + cache = optArgs.get('eventDateTimeEnd', default=None) + if cache is not None: + sqlList.append('[ccn_eventDateTimeEnd] = ?') + argumentsList.append(cache) + cache = optArgs.get('loopRules', default=None) + if cache is not None: + sqlList.append('[ccn_loopRules] = ?') + argumentsList.append(cache) + reAnalyseLoop = True + analyseData[8] = cache + cache = optArgs.get('timezoneOffset', default=None) + if cache is not None: + sqlList.append('[ccn_timezoneOffset] = ?') + argumentsList.append(cache) + reAnalyseLoop = True + analyseData[7] = cache + + if reAnalyseLoop: + pass + # todo: finish this, re-compute loop data and upload it into list + + # execute + argumentsList.append(uuid) + self.cursor.execute('UPDATE calendar SET {} WHERE [ccn_uuid] = ?;'.format(', '.join(sqlList)), + tuple(argumentsList)) + return lastupdate + + @SafeDatabaseOperation + def calendar_add(self, token, belongTo, title, description, eventDateTimeStart, eventDateTimeEnd, loopRules, timezoneOffset): + self.tokenOper_check_valid(token) + + newuuid = utils.GenerateUUID() + lastupdate = utils.GenerateUUID() + + # todo: analyse loopRules and output following 2 fileds. + loopDateTimeStart = eventDateTimeStart + loopDateTimeEnd = eventDateTimeEnd + + self.cursor.execute('INSERT INTO calendar VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);', + (newuuid, + belongTo, + title, + description, + lastupdate, + eventDateTimeStart, + eventDateTimeEnd, + timezoneOffset, + loopRules, + loopDateTimeStart, + loopDateTimeEnd)) + return newuuid + + @SafeDatabaseOperation + def calendar_delete(self, token, uuid, lastChange): + self.tokenOper_check_valid(token) + self.cursor.execute('DELETE FROM calendar WHERE [ccn_uuid] = ? AND [ccn_lastChange] = ?;', (uuid, lastChange)) + return True # =============================== collection @@ -258,16 +376,9 @@ class CalendarDatabase(object): def todo_delete(self, token, uuid, lastChange): # check valid token self.tokenOper_check_valid(token) - # check sync conflict - self.cursor.execute('SELECT [ccn_uuid] FROM todo WHERE [ccn_uuid] = ? AND [ccn_lastChange] = ?;', ( - uuid, - lastChange - )) - if len(self.cursor.fetchall()) == 0: - raise Exception('No matched uuid or not matched sync symbol') # delete - self.cursor.execute('DELETE FROM todo WHERE [ccn_uuid] = ?;', (uuid, )) + self.cursor.execute('DELETE FROM todo WHERE [ccn_uuid] = ? AND [ccn_lastChange] = ?;', (uuid, lastChange)) return True diff --git a/src/server.py b/src/server.py index 31c187b..4daf0c5 100644 --- a/src/server.py +++ b/src/server.py @@ -98,11 +98,14 @@ def api_common_tokenValidHandle(): @app.route('/api/common/isAdmin', methods=['POST']) def api_common_isAdminHandle(): - pass + return SmartDbCaller(calendar_db.common_isAdmin, + (('token', str, False), )) @app.route('/api/common/changePassword', methods=['POST']) def api_common_changePasswordHandle(): - pass + return SmartDbCaller(calendar_db.common_changePassword, + (('token', str, False), + ('password', str, False))) # ================================ calendar diff --git a/src/sql/sqlite.sql b/src/sql/sqlite.sql index 5248e4c..b0ce859 100644 --- a/src/sql/sqlite.sql +++ b/src/sql/sqlite.sql @@ -46,6 +46,7 @@ CREATE TABLE calendar( [ccn_eventDateTimeStart] BIGINT NOT NULL, [ccn_eventDateTimeEnd] BIGINT NOT NULL, + [ccn_timezoneOffset] INT NOT NULL, [ccn_loopRules] TEXT NOT NULL, [ccn_loopDateTimeStart] BIGINT NOT NULL,