aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/css/color.less1
-rw-r--r--src/css/index.less34
-rw-r--r--src/css/mail.less25
-rw-r--r--src/css/style.less20
-rw-r--r--src/css/user_edit.less5
-rw-r--r--src/css/user_main.less15
-rw-r--r--src/html/index.html9
-rw-r--r--src/html/user_edit.html31
-rw-r--r--src/html/user_main.html11
-rw-r--r--src/js/com.js46
-rw-r--r--src/js/imc.js2
-rw-r--r--src/js/index.js29
-rw-r--r--src/js/mail.js18
-rw-r--r--src/js/notice.js66
-rw-r--r--src/js/user.js299
-rwxr-xr-xsrc/py/backend_server.py36
-rwxr-xr-xsrc/py/center_server.py79
-rwxr-xr-xsrc/py/imc/proxy.py9
-rw-r--r--src/py/mail.py15
-rw-r--r--src/py/notice.py236
-rw-r--r--src/py/square.py311
-rwxr-xr-xsrc/py/user.py72
22 files changed, 1234 insertions, 135 deletions
diff --git a/src/css/color.less b/src/css/color.less
index 5752589..c1887c6 100644
--- a/src/css/color.less
+++ b/src/css/color.less
@@ -1,4 +1,5 @@
@white:#FFFFFF;
+@lightgray:#FCFAF2;
@gray:#BDC0BA;
@darkgray:#373C38;
@black:#000000;
diff --git a/src/css/index.less b/src/css/index.less
index d85bcce..81d9546 100644
--- a/src/css/index.less
+++ b/src/css/index.less
@@ -2,12 +2,24 @@
@import 'mixin.less';
body{
+ overflow-x:hidden;
overflow-y:scroll;
}
#index_header{
+ height:0px;
z-index:1;
- position:relative;
+ position:fixed;
+ top:0px;
+ left:0px;
+ opacity:0;
+ transition:opacity @fast;
+
+ &.active{
+ height:40px;
+ opacity:1;
+ display:block;
+ }
}
.index_tag{
height:32px;
@@ -48,6 +60,7 @@ body{
div.notice{
width:70px;
text-align:center;
+ background-color:@darkgray
}
div.notice_hl{
background-color:@orange;
@@ -106,10 +119,14 @@ body{
div.notice{
overflow-y:auto;
- li > a{
- height:64px;
+ ul.nav > li > a{
+ min-height:64px;
padding-left:@SmallPad;
font-size:@NormalFontSize;
+
+ p{
+ word-wrap:break-word;
+ }
}
}
}
@@ -120,9 +137,12 @@ body{
right:@MediumPad;
}
#index_page{
+ margin-top:40px;
padding-top:@MediumPad;
-
- div.page{
-
- }
+}
+#index_footer{
+ margin-top:@MediumPad;
+ padding:@MediumPad @MediumPad 0px @MediumPad;
+ background-color:@lightgray;
+ text-align:right;
}
diff --git a/src/css/mail.less b/src/css/mail.less
index dbfe3f2..e0bd6e7 100644
--- a/src/css/mail.less
+++ b/src/css/mail.less
@@ -1,3 +1,6 @@
+@import "mixin.less";
+@import "color.less";
+
#index_page{
div.newmail{
div.content{
@@ -9,7 +12,29 @@
width:100%;
}
}
+ div.oper{
+ text-align:center;
+ }
table.maillist{
+ position:relative;
+ left:-39px;
+
+ th.check{
+ width:16px;
+ text-align:center;
+
+ span.check{
+ margin-bottom:-2px;
+ }
+ }
+ td.check{
+ width:16px;
+ text-align:center;
+
+ span.check{
+ margin-top:4px;
+ }
+ }
tr.item{
cursor:pointer;
}
diff --git a/src/css/style.less b/src/css/style.less
index 97e519e..c36c429 100644
--- a/src/css/style.less
+++ b/src/css/style.less
@@ -6,6 +6,26 @@ div.medium_modal{
width:970px;
margin-left:-485px;
}
+span.check{
+ width:14px;
+ height:14px;
+ border:@gray 1px solid;
+ position:relative;
+ display:inline-block;
+
+ &:hover{
+ background-color:fade(@black,10%);
+ }
+
+ i{
+ position:absolute;
+ top:-2px;
+ left:0px;
+ }
+}
+span.check_bold{
+ border:@darkgray 2px solid;
+}
.time{
font-size:@SmallFontSize;
}
diff --git a/src/css/user_edit.less b/src/css/user_edit.less
new file mode 100644
index 0000000..6a454f7
--- /dev/null
+++ b/src/css/user_edit.less
@@ -0,0 +1,5 @@
+#index_page{
+ img.avatar,img.cover{
+ width:270px;
+ }
+}
diff --git a/src/css/user_main.less b/src/css/user_main.less
index 33518fe..a136854 100644
--- a/src/css/user_main.less
+++ b/src/css/user_main.less
@@ -1,3 +1,16 @@
-#index_page{
+@import "mixin.less";
+@import "color.less";
+#index_page{
+ div.cover{
+ width:100%;
+ height:900px;
+ overflow-y:hidden;
+ position:absolute;
+ top:0px; left:0px; z-index:0;
+ background-size:cover;
+ }
+ div.profile{
+ color:darken(@gray,20%);
+ }
}
diff --git a/src/html/index.html b/src/html/index.html
index 16b3880..b8795ea 100644
--- a/src/html/index.html
+++ b/src/html/index.html
@@ -23,6 +23,7 @@
<script src="/toj/js/com.js" type="text/javascript"></script>
<script src="/toj/js/index.js" type="text/javascript"></script>
<script src="/toj/js/user.js" type="text/javascript"></script>
+<script src="/toj/js/notice.js" type="text/javascript"></script>
<script src="/toj/js/home.js" type="text/javascript"></script>
<script src="/toj/js/mail.js" type="text/javascript"></script>
@@ -36,6 +37,7 @@ $(document).ready(function(){
com.conn_callback.add(function(){
user.ready();
+ notice.ready();
index.ready();
home.ready();
mail.ready();
@@ -91,7 +93,7 @@ $(document).ready(function(){
</div>
<div id="index_paneltag" class="active">
- <div class="notice notice_hl">[5]</div>
+ <div class="notice"></div>
</div>
<div id="index_panel" exheight=true>
<div class="tagblock"></div>
@@ -122,6 +124,9 @@ $(document).ready(function(){
</div>
<div id="index_alert" style="z-index:2000;"></div>
-<div id="index_page" class="container"></div>
+<div id="index_page" class="container" exminheight=true extop=56px exbottom=62px></div>
+<div id="index_footer">
+ <p class="muted">εpsilon team</p>
+</div>
</body>
</html>
diff --git a/src/html/user_edit.html b/src/html/user_edit.html
new file mode 100644
index 0000000..da8706d
--- /dev/null
+++ b/src/html/user_edit.html
@@ -0,0 +1,31 @@
+<link href="/toj/css/user_edit.css" rel="stylesheet">
+
+<div class="row">
+ <div class="offset3 span3">
+ <h3>個人資料</h3>
+ <label>暱稱</label>
+ <input name="nickname" type="text">
+ <label>信箱</label>
+ <input name="email" type="text">
+ <label>個人頭像網址</label>
+ <input name="avatar" type="text"><br>
+ <img class="img-polaroid avatar"></img><br><br>
+ <label>個人封面網址</label>
+ <input name="cover" type="text"><br>
+ <img class="img-polaroid cover"></img><br><br>
+ <label>關於我</label>
+ <input name="aboutme" type="text"><br>
+ <button class="btn btn-primary submit">確定</button>
+ <button class="btn cancel">取消</button>
+
+ <h3>更改密碼</h3>
+ <label>舊密碼</label>
+ <input name="oldpassword" type="password">
+ <label>新密碼</label>
+ <input name="password" type="password">
+ <label>重複密碼</label>
+ <input name="repeat" type="password"><br>
+ <button class="btn btn-primary submit">確定</button>
+ <button class="btn cancel">取消</button>
+ </div>
+</div>
diff --git a/src/html/user_main.html b/src/html/user_main.html
index ae8b25d..ad0755d 100644
--- a/src/html/user_main.html
+++ b/src/html/user_main.html
@@ -1,12 +1,11 @@
<link href="/toj/css/user_main.css" rel="stylesheet">
-<div style="width:100%; max-height:900px; overflow-y:hidden; position:absolute; top:0px; left:0px; z-index:0;">
- <img src="http://i.imgur.com/Btrg9wz.jpg"></img>
-</div>
-<div class="row" style="height:768px; margin-top:560px; position:relative; z-index:0;">
+
+<div class="cover"></div>
+<div class="row" style="height:768px; margin-top:640px; position:relative; z-index:0;">
<div class="offset4 span2">
- <img class="img-polaroid avatar" src="http://i.imgur.com/R9lfWcm.jpg"></img>
+ <img class="img-polaroid avatar"></img>
</div>
- <div class="span7" style="color:white;">
+ <div class="span3 profile">
<h3 class="name"></h3>
<h3>關於我</h3>
<p class="aboutme"></p>
diff --git a/src/js/com.js b/src/js/com.js
index 4105dd6..3e50173 100644
--- a/src/js/com.js
+++ b/src/js/com.js
@@ -201,7 +201,9 @@ var com = new function(){
that.url_chg();
};
that.url_push_back = function(block_regexp){
- if(that.url_back == null || that.url_back.search(block_regexp) != -1){
+ console.log(that.url_back);
+
+ if(that.url_back == null || (block_regexp != undefined && that.url_back.search(block_regexp) != -1)){
that.url_push('/toj/home/');
}else{
that.url_push(that.url_back);
@@ -466,28 +468,37 @@ var com = new function(){
};
that.exheight = function(){
var i;
- var es = $('[exheight="true"]');
var j_e;
var winheight = $(window).innerHeight();
var exratio;
var extop;
+ var exbottom;
- for(i = 0;i < es.length;i++){
- j_e = $(es[i]);
+ function ex(es,attr){
+ for(i = 0;i < es.length;i++){
+ j_e = $(es[i]);
- if((exratio = j_e.attr('exratio')) != undefined){
- exratio = parseInt(exratio.match('(.*)%')[1]) / 100;
- j_e.height(winheight * exratio);
- }else{
- if((extop = j_e.attr('extop')) == undefined){
- extop = j_e.css('top');
- }
+ if((exratio = j_e.attr('exratio')) != undefined){
+ exratio = parseInt(exratio.match('(.*)%')[1]) / 100;
+ j_e.height(winheight * exratio);
+ }else{
+ if((extop = j_e.attr('extop')) == undefined){
+ extop = j_e.css('top');
+ }
+ if((exbottom = j_e.attr('exbottom')) == undefined){
+ exbottom = '0px';
+ }
- extop = extop.match('(.*)px')[1];
- j_e.height(winheight - extop);
+ extop = extop.match('(.*)px')[1];
+ exbottom = exbottom.match('(.*)px')[1];
+ j_e.css(attr,(winheight - extop - exbottom));
+ }
}
}
+ ex($('[exheight="true"]'),'height');
+ ex($('[exminheight="true"]'),'min-height');
+
$('.modal-body').css('max-height',(winheight * 0.5) + 'px');
};
that.get_cookie = function(){
@@ -673,12 +684,13 @@ var com = new function(){
imc.Auth.change_current_iden(idendesc)
- if((cookie = com.get_cookie()) != null){
- com.call_backend('core/user/','cookie_login',function(result){
- if(com.is_callerr(result)){
+ if((cookie = that.get_cookie()) != null){
+ that.call_backend('core/user/','cookie_login',function(result){
+ if(that.is_callerr(result)){
//TODO GE
}else{
imc.Auth.change_current_iden(result.data.idendesc);
+ user.uid = imc.Auth.get_current_iden().uid;
}
that.conn_callback.fire();
@@ -696,7 +708,7 @@ var com = new function(){
var i;
var params = new Array()
- params = [com.backend_link + path,func_name,1000,callback]
+ params = [that.backend_link + path,func_name,1000,callback]
for(i = 3;i < arguments.length;i++){
params.push(arguments[i]);
}
diff --git a/src/js/imc.js b/src/js/imc.js
index 8970ccf..aea4a03 100644
--- a/src/js/imc.js
+++ b/src/js/imc.js
@@ -87,6 +87,8 @@ var imc = new function(){
}
};
+ console.log(func_name);
+
part = dst.split('/');
dst_link = part.slice(0,3).join('/') + '/'
dst_path = part.slice(3,-1);
diff --git a/src/js/index.js b/src/js/index.js
index 9f1ba44..3ea93fc 100644
--- a/src/js/index.js
+++ b/src/js/index.js
@@ -10,11 +10,19 @@ var index = new function(){
var j_header;
var j_alertbox;
+ function active_header(){
+ j_header.addClass('active');
+ }
+ function inactive_header(){
+ if(j_win.scrollTop() > 8 && !j_header.hasClass('force')){
+ j_header.removeClass('active');
+ }
+ }
function active_menutag(){
j_menutag.addClass('active');
};
function inactive_menutag(){
- if(j_win.scrollTop() > 8 && !j_menu.hasClass('active')){
+ if(j_win.scrollTop() > 8 && !j_menutag.hasClass('force') && !j_menu.hasClass('active')){
j_menutag.removeClass('active');
}
};
@@ -22,7 +30,7 @@ var index = new function(){
j_paneltag.addClass('active');
};
function inactive_paneltag(){
- if(j_win.scrollTop() > 8 && !j_panel.hasClass('active')){
+ if(j_win.scrollTop() > 8 && !j_paneltag.hasClass('force') && !j_panel.hasClass('active')){
j_paneltag.removeClass('active');
}
};
@@ -51,15 +59,21 @@ var index = new function(){
j_panel = $('#index_panel');
j_header = $('#index_header');
j_alertbox = $('#index_alert');
-
- j_win.on('scroll',function(e){
+
+ function _change(){
if(j_win.scrollTop() <= 8){
+ active_header();
active_menutag();
active_paneltag();
}else{
+ inactive_header();
inactive_menutag();
inactive_paneltag();
}
+ }
+
+ j_win.on('scroll',function(e){
+ _change();
});
j_win.on('mouseover',function(e){
var j_e;
@@ -92,6 +106,11 @@ var index = new function(){
active_panel();
}
});
+ j_panel.find('div.notice').on('click',function(e){
+ if(j_panel.hasClass('active')){
+ inactive_panel();
+ }
+ });
user.login_callback.add(function(){
var j_li;
@@ -102,6 +121,8 @@ var index = new function(){
j_menu.find('div.menu li.mail').show();
});
+
+ _change();
};
that.set_title = function(title){
j_header.find('p.title').text(title);
diff --git a/src/js/mail.js b/src/js/mail.js
index 780aa90..0abe12a 100644
--- a/src/js/mail.js
+++ b/src/js/mail.js
@@ -51,6 +51,10 @@ var mail = new function(){
return j_item;
};
function update_maillist(){
+ if(maillist_type == null){
+ return;
+ }
+
j_index_page.find('span.checkall').check(false);
com.call_backend('core/mail/','list_mail',function(result){
@@ -90,6 +94,11 @@ var mail = new function(){
var backup_node = new vus.node('backup');
j_index_page = $('#index_page');
+
+ imc.Proxy.instance.register_call('core/mail/','update_mail',function(callback){
+ update_maillist();
+ callback('Success');
+ });
mail_node.url_chg = function(direct,url_upart,url_dpart,param){
if(direct == 'in'){
@@ -152,8 +161,6 @@ var mail = new function(){
j_newmail.on('hide',function(e){
j_newmail.find('input').val('');
newmail_content.setValue('');
-
- update_maillist();
});
j_newmail.find('button.submit').on('click',function(e){
var to_username = j_newmail.find('input.to_username').val();
@@ -212,6 +219,7 @@ var mail = new function(){
j_readmail.find('h3.title').text('');
j_readmail.find('span.from_username').text('');
readmail_content.setValue('');
+ readmail_mailid = null;
update_maillist();
});
@@ -270,6 +278,9 @@ var mail = new function(){
},maillist_type);
update_maillist();
+ }else if(direct == 'out'){
+ maillist_type = null;
+ maillist_off = null;
}
return 'cont';
@@ -306,6 +317,9 @@ var mail = new function(){
},maillist_type);
update_maillist();
+ }else if(direct == 'out'){
+ maillist_type = null;
+ maillist_off = null;
}
return 'cont';
diff --git a/src/js/notice.js b/src/js/notice.js
new file mode 100644
index 0000000..9bd92eb
--- /dev/null
+++ b/src/js/notice.js
@@ -0,0 +1,66 @@
+var notice = new function(){
+ var that = this;
+ var j_noticetag;
+ var j_noticelist;
+
+ that.ready = function(){
+ function _set_unseen_count(count){
+ if(count == 0){
+ j_noticetag.removeClass('notice_hl');
+ }else{
+ j_noticetag.addClass('notice_hl');
+ }
+ j_noticetag.text('[' + count + ']');
+ }
+
+ j_noticetag = $('#index_paneltag > div.notice');
+ j_noticelist = $('#index_panel > div.notice > ul.nav');
+
+ j_noticetag.on('click',function(e){
+ j_noticelist.empty();
+
+ com.call_backend('core/notice/','list_notice',function(result){
+ var i;
+ var data = result.data;
+ var notice;
+ var j_item;
+
+ if(com.is_callerr(result)){
+ index.add_alert('','警告','通知發生錯誤');
+ }else{
+ console.log(data);
+
+ for(i = 0;i < data.length;i++){
+ notice = data[i];
+
+ j_item = $('<li><a><h5></h5><p></p></a></li>');
+ j_item.find('h5').text(notice.title);
+ j_item.find('p').text(notice.content);
+
+ if(notice.noticemodid == null){
+ j_item.find('a').attr('href','/toj' + notice.metadata);
+ }
+
+ j_noticelist.append(j_item);
+ }
+ }
+ });
+ });
+
+ imc.Proxy.instance.register_call('core/notice/','update_notice',function(callback,unseen_count){
+ _set_unseen_count(unseen_count);
+ callback('Success');
+ });
+
+ com.call_backend('core/notice/','get_unseen_count',function(result){
+ var data = result.data;
+
+ if(com.is_callerr(result)){
+ index.add_alert('','警告','通知發生錯誤');
+ }else{
+ _set_unseen_count(data.unseen_count);
+ }
+ });
+ };
+
+};
diff --git a/src/js/user.js b/src/js/user.js
index 259768d..f6d32b9 100644
--- a/src/js/user.js
+++ b/src/js/user.js
@@ -7,15 +7,19 @@ var user = new function(){
that.nickname = null;
that.email = null;
that.avatar = null;
+ that.cover = null;
that.login_callback = $.Callbacks();
that.ready = function(){
var uid;
var user_node_uid = null;
+ var j_tabnav_main;
+ var j_tabnav_edit;
var user_node = new vus.node('user');
var main_node = new vus.node('main');
+ var edit_node = new vus.node('edit');
var login_node = new vus.node('login');
var register_node = new vus.node('register');
var logout_node = new vus.node('logout');
@@ -29,7 +33,9 @@ var user = new function(){
document.cookie = 'hash=' + hash + ';path=/;expires=' + expire.toUTCString();
imc.Auth.change_current_iden(idendesc);
- _set_user_data(uid);
+ _set_user_data(uid).done(function(){
+ that.login_callback.fire();
+ });
};
function _logout(){
document.cookie = 'uid=;path=/;expires=Thu, 01 Jan 1970 00:00:00 GMT';
@@ -49,71 +55,293 @@ var user = new function(){
return defer.promise();
};
function _set_user_data(uid){
+ var defer = $.Deferred();
+
_get_user_info(uid).done(function(data){
+ var j_a;
+
that.uid = data.uid;
that.username = data.username;
that.nickname = data.nickname;
that.email = data.email;
that.avatar = data.avatar;
+ that.cover = data.cover;
- that.login_callback.fire();
+ j_a = $('#index_header li.nickname > a');
+ j_a.text(that.nickname);
+ j_a.attr('href','/toj/user:' + that.uid + '/main/');
+ defer.resolve();
}).fail(function(data){
- //TODO GE
+ defer.reject();
});
+
+ return defer.promise();
}
j_index_page = $('#index_page');
if((uid = imc.Auth.get_current_iden().uid) != undefined){
- _set_user_data(uid);
+ _set_user_data(uid).done(function(){
+ that.login_callback.fire();
+ });
}
user_node.url_chg = function(direct,url_upart,url_dpart,param){
- if(direct == 'in'){
- user_node_uid = parseInt(param[0]);
+ var param_uid;
+
+ if(direct == 'in' || direct == 'same'){
+ if((param_uid = parseInt(param[0])) == user_node_uid){
+ return 'cont';
+ }
+ user_node_uid = param_uid;
+
+ index.set_menu('使用者');
+ index.set_title('');
+
+ index.clear_tabnav();
+
+ j_tabnav_main = index.add_tabnav('個人','/toj/user:' + user_node_uid + '/main/');
+
+ if(user_node_uid == that.uid){
+ j_tabnav_edit = index.add_tabnav('編輯資料','/toj/user:' + user_node_uid + '/edit/');
+ user_node.child_set(edit_node);
+ }
+ }else if(direct == 'out'){
+ user_node_uid = null;
+ user_node.child_del(edit_node);
}
};
com.vus_root.child_set(user_node);
- function _tmp(y){
- var now = 0;
- var ay = 80;
+ main_node.url_chg = function(direct,url_upart,url_dpart,param){
+ var j_win = $(window);
+ var j_header = $('#index_header');
+ var j_menutag = $('#index_menutag');
+ var j_paneltag = $('#index_paneltag');
- function __ani(){
- if(y <= now){
- $(window).scrollTop(y);
- return;
+ function _tmp(y){
+ var now = 0;
+ var ay = 100;
+
+ /*function __ani(){
+ if(y <= now){
+ $(window).scrollTop(y);
+ return;
+ }
+ $(window).scrollTop(now);
+
+ now = now + ay;
+ ay = Math.max(5,ay * 0.86);
+ setTimeout(__ani,10);
}
- $(window).scrollTop(now);
- now = now + ay;
- ay = Math.max(5,ay * 0.86);
- setTimeout(__ani,10);
+ __ani();*/
+ j_win.scrollTop(y);
}
- __ani();
- }
+ function _active(){
+ j_header.addClass('force');
+ j_header.addClass('active');
+ j_menutag.addClass('force');
+ j_menutag.addClass('active');
+ j_paneltag.addClass('force');
+ j_paneltag.addClass('active');
+ }
+ function _inactive(){
+ j_header.removeClass('force');
+ j_menutag.removeClass('force');
+ j_paneltag.removeClass('force');
+ }
- main_node.url_chg = function(direct,url_upart,url_dpart,param){
- if(direct == 'in'){
- index.set_menu('使用者');
- index.set_title('');
- index.clear_tabnav();
+ if(direct == 'in' || direct == 'same'){
+ j_tabnav_main.active();
+
+ j_index_page.css('visibility','hidden');
$.when(
_get_user_info(user_node_uid),
com.loadpage('/toj/html/user_main.html')
).done(function(data){
+ var reen = false;
+ var url;
+
+ if((url = data.avatar) == ''){
+ url = 'http://i.imgur.com/ykkQD.png';
+ }
+ j_index_page.find('img.avatar').attr('src',url);
+ if((url = data.cover) == ''){
+ url = 'http://i.imgur.com/7COsFS4.jpg';
+ }
+ j_index_page.find('div.cover').css('background-image','url(\'' + url + '\')');
j_index_page.find('h3.name').text(data.nickname + '(' + data.username + ')');
j_index_page.find('p.aboutme').text(data.aboutme);
- _tmp(560);
+ j_win.on('scroll.user_main',function(e){
+ if(reen == true){
+ return;
+ }
+ reen = true;
+
+ if(j_win.scrollTop() > 500){
+ _inactive();
+ j_win.scroll();
+ }else{
+ _active();
+ }
+
+ reen = false;
+ });
+
+ _active();
+ _tmp(500);
+ j_index_page.show();
+ j_index_page.css('visibility','visible');
});
+ }else if(direct == 'out'){
+ console.log(direct);
+ j_win.off('scroll.user_main');
+ _inactive();
}
+
+ return 'cont';
};
user_node.child_set(main_node);
+ edit_node.url_chg = function(direct,url_upart,url_dpart,param){
+ if(direct == 'in' || direct == 'same'){
+ j_tabnav_edit.active();
+
+ $.when(
+ _get_user_info(user_node_uid),
+ com.loadpage('/toj/html/user_edit.html')
+ ).done(function(data){
+ var j_nickname = j_index_page.find('[name="nickname"]');
+ var j_email = j_index_page.find('[name="email"]');
+ var j_avatar = j_index_page.find('[name="avatar"]');
+ var j_cover = j_index_page.find('[name="cover"]');
+ var j_aboutme = j_index_page.find('[name="aboutme"]');
+ var j_oldpassword = j_index_page.find('[name="oldpassword"]');
+ var j_password = j_index_page.find('[name="password"]');
+ var j_repeat = j_index_page.find('[name="repeat"]');
+ var j_img_avatar = j_index_page.find('img.avatar');
+ var j_img_cover = j_index_page.find('img.cover');
+
+ j_avatar.on('change',function(e){
+ var url = $(this).val();
+
+ if(url == ''){
+ url = 'http://i.imgur.com/ykkQD.png';
+ }
+ j_img_avatar.attr('src',url);
+ });
+ j_cover.on('change',function(e){
+ var url = $(this).val();
+
+ if(url == ''){
+ url = 'http://i.imgur.com/7COsFS4.jpg';
+ }
+ j_img_cover.attr('src',url);
+ });
+
+ j_nickname.val(data.nickname);
+ j_email.val(data.email);
+ j_avatar.val(data.avatar);
+ j_avatar.change();
+ j_cover.val(data.cover);
+ j_cover.change();
+ j_aboutme.val(data.aboutme);
+
+ j_index_page.find('button.submit').on('click',function(e){
+ var oldpassword;
+ var password;
+ var repeat;
+ var set_defer = $.Deferred();
+ var change_defer = $.Deferred();
+
+ oldpassword = j_oldpassword.val();
+ password = j_password.val();
+ repeat = j_repeat.val();
+
+ if(password != repeat){
+ index.add_alert('alert-error','失敗','重複密碼不同',true);
+ return;
+ }
+
+ com.call_backend('core/user/','set_user_info',function(result){
+ var errmsg;
+
+ if(com.is_callerr(result)){
+ if(result.data == 'Eusername_too_short'){
+ errmsg = '使用者名稱過短';
+ }else if(data == 'Eusername_too_long'){
+ errmsg = '使用者名稱過長';
+ }else if(data == 'Eavatar_too_short'){
+ errmsg = '個人頭像網址過短';
+ }else if(data == 'Eavatar_too_long'){
+ errmsg = '個人頭像網址過長';
+ }else if(data == 'Enickname_too_short'){
+ errmsg = '暱稱過短';
+ }else if(data == 'Enickname_too_long'){
+ errmsg = '暱稱過長';
+ }else if(data == 'Eemail_too_short'){
+ errmsg = '信箱過短';
+ }else if(data == 'Eemail_too_long'){
+ errmsg = '信箱過長';
+ }else{
+ errmsg = '資料更新時發生錯誤';
+ }
+
+ index.add_alert('alert-error','失敗',errmsg,true);
+ set_defer.reject();
+ }else{
+ _set_user_data(that.uid);
+ set_defer.resolve();
+ }
+ },that.uid,j_nickname.val(),j_email.val(),j_avatar.val(),j_aboutme.val(),j_cover.val());
+
+ if(oldpassword == ''){
+ change_defer.resolve();
+ }else{
+ com.call_backend('core/user/','change_user_password',function(result){
+ var errmsg;
+
+ console.log(result);
+ if(com.is_callerr(result)){
+ if(result.data == 'Epassword_too_short'){
+ errmsg = '密碼過短';
+ }else if(data == 'Epsaaword_too_long'){
+ errmsg = '密碼過長';
+ }else if(data == 'Ewrong_old_password'){
+ errmsg = '舊密碼錯誤';
+ }else{
+ errmsg = '密碼更改時發生錯誤';
+ }
+
+ index.add_alert('alert-error','失敗',errmsg,true);
+ change_defer.reject();
+ }else{
+ change_defer.resolve();
+ }
+ },that.uid,oldpassword,password);
+ }
+
+ $.when(set_defer,change_defer).done(function(){
+ index.add_alert('alert-success','成功','資料已更新',true);
+ com.url_push('/toj/user:' + that.uid + '/main/');
+ });
+ });
+ j_index_page.find('button.cancel').on('click',function(e){
+ com.url_push_back('/toj/user.*/edit/');
+ });
+ });
+ }else if(direct == 'out'){
+
+ }
+
+ return 'cont';
+ };
+
login_node.url_chg = function(direct,url_upart,url_dpart,param){
if(direct == 'in'){
index.set_menu('登入');
@@ -139,12 +367,12 @@ var user = new function(){
com.call_backend('core/user/','login',function(result){
data = result.data;
- if(result.stat == true && typeof(data) != 'string'){
- _login(data.uid,data.hash,data.idendesc);
- com.url_push('/toj/home/');
- }else{
+ if(com.is_callerr(result)){
j_alert.text('登入失敗');
j_alert.show();
+ }else{
+ _login(data.uid,data.hash,data.idendesc);
+ com.url_push_back('/toj/(login/|register)/');
}
},username,password);
});
@@ -186,8 +414,10 @@ var user = new function(){
com.call_backend('core/user/','login',function(result){
data = result.data;
_login(data.uid,data.hash,data.idendesc);
+ com.url_push_back('/toj/(login/|register)/');
},username,password);
}else{
+ console.log(data);
if(data == 'Eusername_too_short'){
j_alert.text('使用者名稱過短');
}else if(data == 'Eusername_too_long'){
@@ -206,11 +436,13 @@ var user = new function(){
j_alert.text('信箱過長');
}else if(data == 'Eusername_exists'){
j_alert.text('使用者名稱已存在');
+ }else{
+ j_alert.text('註冊時發生錯誤');
}
j_alert.show();
}
- },username,password,nickname,email,'','');
+ },username,password,nickname,email,'','','');
});
});
}
@@ -227,12 +459,7 @@ var user = new function(){
that.login_callback.add(function(){
var j_index_header = $('#index_header');
- var j_a;
-
- j_a = j_index_header.find('li.nickname > a');
- j_a.text(that.nickname);
- j_a.attr('href','/toj/user:' + that.uid + '/main/');
-
+
j_index_header.find('li.login').hide();
j_index_header.find('li.register').hide();
j_index_header.find('li.nickname').show();
diff --git a/src/py/backend_server.py b/src/py/backend_server.py
index 197d820..b9bb07b 100755
--- a/src/py/backend_server.py
+++ b/src/py/backend_server.py
@@ -14,12 +14,14 @@ import tornado.websocket
from imc import auth
import imc.async
-from imc.proxy import Proxy,Connection,imc_call,imc_call_async,imc_register_call
+from imc.proxy import Proxy,Connection
import netio
from netio import SocketStream,SocketConnection,WebSocketConnection
from tojauth import TOJAuth
-import mod
+from notice import Notice
+from user import UserMg
+from mail import Mail
class BackendWorker(tornado.tcpserver.TCPServer):
def __init__(self,center_addr,ws_port):
@@ -113,8 +115,15 @@ class BackendWorker(tornado.tcpserver.TCPServer):
Proxy.instance.register_call('test/','test_dst',self._test_dst)
#Proxy.instance.register_filter('test/',self._test_filter)
- mod.load('core_user','user',self._idendesc,self._get_link)
- mod.load('core_mail','mail',self._idendesc,self._get_link)
+ try:
+ Notice(self._idendesc,self._get_link)
+ UserMg(self._idendesc,self._get_link)
+ Mail(self._idendesc,self._get_link)
+ except Exception as e:
+ print(e)
+
+ #mod.load('core_user','user',self._idendesc,self._get_link)
+ #mod.load('core_mail','mail',self._idendesc,self._get_link)
#if self._link == '/backend/2/':
# self._test_call(None)
@@ -178,6 +187,9 @@ class BackendWorker(tornado.tcpserver.TCPServer):
with TOJAuth.change_current_iden(self._idendesc):
stat,ret = Proxy.instance.call(self.center_conn.link,'lookup_link',65536,link)
+ print(link)
+ print(ret)
+
if stat == False or ret == None:
return None
@@ -236,10 +248,15 @@ class BackendWorker(tornado.tcpserver.TCPServer):
except KeyError:
pass
- def _get_link(self,linkclass):
+ def _get_link(self,linkclass,uid = None):
if linkclass == 'center':
return self.center_conn.link
+ elif linkclass == 'client' and uid != None:
+ stat,ret = Proxy.instance.call(self.center_conn.link + 'core/','get_uid_clientlink',10000,uid)
+ print(ret)
+ return ret
+
@imc.async.caller
def _test_get_client_list(self,talk,talk2):
stat,ret = Proxy.instance.call(TOJAuth.get_current_iden()['link'] + 'test/route/','80s',1000,'attation','mega')
@@ -262,18 +279,13 @@ class BackendWorker(tornado.tcpserver.TCPServer):
continue
fileres = Proxy.instance.sendfile(dst,'Fedora-18-x86_64-DVD.iso')
- ret = imc_call_async(dst + 'test/','test_dst',lambda result: print('ok'),fileres.filekey)
+ ret = Proxy.instance.call_async(dst + 'test/','test_dst',lambda result: print('ok'),fileres.filekey)
print(fileres.wait())
print(time.perf_counter() - st)
print(self._link)
- #imc_call_async(dst,'test_dst',lambda result : print(result),'test',113)
-
- #ret = imc_call('/center/1/','create_iden','client','1234',1221,TOJAuth.ROLETYPE_USER,{'uid':31})
- #print(ret)
-
return
pend = []
@@ -284,7 +296,7 @@ class BackendWorker(tornado.tcpserver.TCPServer):
fileres = Proxy.instance.sendfile('/backend/' + str((i % 16) + 2) + '/','Fedora-18-x86_64-DVD.iso')
dst = '/backend/' + str((i % 16) + 2) + '/'
- ret = imc_call(self._idendesc,dst,'test_dst',fileres.filekey)
+ ret = Proxy.instance.call(self._idendesc,dst,'test_dst',fileres.filekey)
pend.append(fileres)
diff --git a/src/py/center_server.py b/src/py/center_server.py
index 1f67c9d..bed117d 100755
--- a/src/py/center_server.py
+++ b/src/py/center_server.py
@@ -11,7 +11,7 @@ import tornado.httpserver
import tornado.web
import imc.async
-from imc.proxy import Proxy,Connection,imc_call,imc_call_async,imc_register_call
+from imc.proxy import Proxy,Connection
import netio
from netio import SocketStream,SocketConnection
@@ -62,6 +62,7 @@ class CenterServer(tornado.tcpserver.TCPServer):
self._client_linkmap = {}
self._client_backendmap = {}
self._backend_workerlist = []
+ self._uid_clientmap = {}
pubkey = open('pubkey.pem','r').read()
privkey = open('privkey.pem','r').read()
@@ -72,12 +73,13 @@ class CenterServer(tornado.tcpserver.TCPServer):
self._idendesc = TOJAuth.instance.create_iden(self._link,1,TOJAuth.ROLETYPE_TOJ)
Proxy(self._link,TOJAuth.instance,self._idendesc)
- imc_register_call('','lookup_link',self._lookup_link)
- imc_register_call('','create_iden',self._create_iden)
- imc_register_call('','add_client',self._add_client)
- imc_register_call('','del_client',self._del_client)
+ Proxy.instance.register_call('','lookup_link',self._lookup_link)
+ Proxy.instance.register_call('','create_iden',self._create_iden)
+ Proxy.instance.register_call('','add_client',self._add_client)
+ Proxy.instance.register_call('','del_client',self._del_client)
+ Proxy.instance.register_call('core/','get_uid_clientlink',self._get_uid_clientlink)
- imc_register_call('test/','get_client_list',self._test_get_client_list)
+ Proxy.instance.register_call('test/','get_client_list',self._test_get_client_list)
def handle_stream(self,stream,addr):
def _recv_worker_info(data):
@@ -150,18 +152,30 @@ class CenterServer(tornado.tcpserver.TCPServer):
#else:
# worker = self._worker_linkidmap[str(a - 1)]
- linkclass = TOJAuth.get_current_iden()['link'].split('/',2)[1]
- if linkclass != 'client':
- worker = self._worker_linkmap[link]
-
- sock_ip,sock_port = worker.sock_addr
- return {
- 'worker_link':worker.link,
- 'sock_ip':sock_ip,
- 'sock_port':sock_port
- }
+ if TOJAuth.get_current_iden()['link'].split('/')[1] != 'client':
+ linkclass,linkid = link.split('/')[1:3]
+
+ if linkclass == 'client':
+ backend_link = self._client_linkmap[link]['backend_link']
+ worker = self._worker_linkmap[backend_link]
+
+ sock_ip,sock_port = worker.sock_addr
+ return {
+ 'worker_link':worker.link,
+ 'sock_ip':sock_ip,
+ 'sock_port':sock_port
+ }
+
+ else:
+ worker = self._worker_linkmap[link]
+
+ sock_ip,sock_port = worker.sock_addr
+ return {
+ 'worker_link':worker.link,
+ 'sock_ip':sock_ip,
+ 'sock_port':sock_port
+ }
- else:
return None
except KeyError:
@@ -170,13 +184,27 @@ class CenterServer(tornado.tcpserver.TCPServer):
@imc.async.caller
@TOJAuth.check_access(1,TOJAuth.ACCESS_EXECUTE)
def _create_iden(self,link,idenid,roletype,payload):
+ linkclass = link.split('/')[1]
+ if linkclass == 'client' and roletype == TOJAuth.ROLETYPE_USER:
+ uid = payload['uid']
+ client = self._client_linkmap[link]
+ client['uid'] = uid
+
+ if uid not in self._uid_clientmap:
+ self._uid_clientmap[uid] = {link:client}
+
+ else:
+ self._uid_clientmap[uid][link] = client
+
return TOJAuth.instance.create_iden(link,idenid,roletype,payload)
@imc.async.caller
@TOJAuth.check_access(1,TOJAuth.ACCESS_EXECUTE)
def _add_client(self,client_link,backend_link):
self._client_linkmap[client_link] = {
- 'backend_link':backend_link
+ 'client_link':client_link,
+ 'backend_link':backend_link,
+ 'uid':None
}
self._client_backendmap[backend_link].add(client_link)
@@ -188,13 +216,28 @@ class CenterServer(tornado.tcpserver.TCPServer):
@imc.async.caller
@TOJAuth.check_access(1,TOJAuth.ACCESS_EXECUTE)
def _del_client(self,client_link,backend_link):
+ uid = self._client_linkmap[client_link]['uid']
+
+ if uid != None:
+ clients = self._uid_clientmap[uid]
+ del clients[client_link]
+
+ if len(clients) == 0:
+ del self._uid_clientmap[uid]
+
del self._client_linkmap[client_link]
self._client_backendmap[backend_link].remove(client_link)
Proxy.instance.unlink_conn(client_link)
+ @imc.async.caller
+ def _get_uid_clientlink(self,uid):
+ if uid in self._uid_clientmap:
+ clients = self._uid_clientmap[uid]
+ return list(clients.keys())
+ return []
@imc.async.caller
def _test_get_client_list(self,talk,talk2):
diff --git a/src/py/imc/proxy.py b/src/py/imc/proxy.py
index 8f750c0..da4bfd4 100755
--- a/src/py/imc/proxy.py
+++ b/src/py/imc/proxy.py
@@ -621,12 +621,3 @@ class Proxy:
def _abort_sendfile(self,filekey):
if filekey in self._info_filekeymap:
self._ioloop.add_callback(self._ret_sendfile,filekey,'Eabort')
-
-def imc_call(dst,func_name,*args):
- return Proxy.instance.call(dst,func_name,65536,*args)
-
-def imc_call_async(dst,func_name,callback,*args):
- Proxy.instance.call_async(dst,func_name,65536,callback,*args)
-
-def imc_register_call(path,func_name,func):
- Proxy.instance.register_call(path,func_name,func)
diff --git a/src/py/mail.py b/src/py/mail.py
index d3e2fd6..aa01dd6 100644
--- a/src/py/mail.py
+++ b/src/py/mail.py
@@ -1,6 +1,7 @@
from tojauth import TOJAuth
from asyncdb import AsyncDB
from user import UserMg
+from notice import Notice
from imc.proxy import Proxy
import imc.proxy
import config
@@ -70,7 +71,12 @@ class Mail:
self._add_mail(
uid, to_uid, self.MAIL_TYPE_SENT_BACKUP, False, title, content
)
-
+ username = UserMg.instance.get_user_info_by_uid(uid)['username']
+ Notice.instance.send_notice(
+ to_uid, 'Mail From ' + username, title, None, '/mail/inbox/'
+ )
+ self.notify_client(uid)
+ self.notify_client(to_uid)
@TOJAuth.check_access(_accessid, TOJAuth.ACCESS_EXECUTE)
def _add_mail(self, uid, from_uid, mail_type, unread, title, content):
@@ -254,6 +260,13 @@ class Mail:
count = data[0]
return count
+
+ @TOJAuth.check_access(_accessid, TOJAuth.ACCESS_EXECUTE)
+ def notify_client(self, uid):
+ for link in self.get_link('client', uid = uid):
+ Proxy.instance.call_async(
+ link + 'core/mail/', 'update_mail', 10000, None
+ )
def load(mod_idendesc, get_link_fn):
Mail(mod_idendesc, get_link_fn)
diff --git a/src/py/notice.py b/src/py/notice.py
new file mode 100644
index 0000000..3a0a988
--- /dev/null
+++ b/src/py/notice.py
@@ -0,0 +1,236 @@
+from tojauth import TOJAuth
+from asyncdb import AsyncDB
+
+from imc.proxy import Proxy
+import imc.proxy
+import config
+
+class Notice:
+ _accessid = 5
+
+ NOTICE_LIST_NUM = 10
+
+ def __init__(self, mod_idendesc, get_link_fn):
+ Notice.instance = self
+ Notice.db = AsyncDB(config.CORE_DBNAME, config.CORE_DBUSER,
+ config.CORE_DBPASSWORD)
+ Notice._idendesc = mod_idendesc
+ self.get_link = get_link_fn
+
+ Proxy.instance.register_call(
+ 'core/notice/', 'list_notice', self.list_notice)
+ Proxy.instance.register_call(
+ 'core/notice/', 'read_notice', self.read_notice)
+ Proxy.instance.register_call(
+ 'core/notice/', 'del_notice', self.del_notice)
+ Proxy.instance.register_call(
+ 'core/notice/', 'get_unseen_count', self.get_unseen_count)
+
+ @TOJAuth.check_access(_accessid, TOJAuth.ACCESS_EXECUTE)
+ def send_notice(self, uid, title, content, noticemod_path, metadata):
+ cur = self.db.cursor()
+
+ noticemodid = None
+
+ if noticemod_path != None:
+ sqlstr = ('SELECT "noticemodid" FROM "NOTICEMOD" WHERE "path" '
+ '= %s;')
+ sqlarr = (noticemod_path, )
+ cur.execute(sqlstr, sqlarr)
+
+ for data in cur:
+ noticemodid = data[0]
+
+ if noticemodid == None:
+ sqlstr = ('INSERT INTO "NOTICEMOD" ("path") VALUES (%s) '
+ 'RETURNING "noticemodid";')
+ sqlarr = (noticemod_path, )
+ cur.execute(sqlstr, sqlarr)
+ for data in cur:
+ noticemodid = data[0]
+
+ sqlstr = ('INSERT INTO "NOTICE" ("uid", "title", "content", '
+ '"noticemodid", "metadata") VALUES (%s, %s, %s, %s, %s) '
+ 'RETURNING "noticeid";')
+ sqlarr = (uid, title, content, noticemodid, metadata)
+ cur.execute(sqlstr, sqlarr)
+
+ noticeid = None
+ for data in cur:
+ noticeid = data[0]
+
+ unseen_count = self._get_unseen_count(uid)
+ self.set_unseen_count(uid, unseen_count + 1)
+
+ return noticeid
+
+ @imc.async.caller
+ def del_notice(self, noticeid):
+ if(
+ type(noticeid) != int
+ ):
+ return 'Eparameter'
+
+ notice = self.get_notice(noticeid)
+ if notice == None:
+ return 'Enoticeid'
+
+ with TOJAuth.change_current_iden(self._idendesc):
+ self._del_notice(noticeid)
+ self.notify_client(notice['uid'])
+
+ @TOJAuth.check_access(_accessid, TOJAuth.ACCESS_EXECUTE)
+ def _del_notice(self, noticeid):
+ cur = self.db.cursor()
+ sqlstr = ('DELETE FROM "NOTICE" WHERE "noticeid" = %s;')
+ sqlarr = (noticeid, )
+ cur.execute(sqlstr, sqlarr)
+
+ @imc.async.caller
+ def list_notice(self, start_index = 0, list_num = NOTICE_LIST_NUM):
+ if(
+ type(start_index) != int or
+ type(list_num) != int
+ ):
+ return 'Eparameter'
+
+ uid = UserMg.get_current_uid()
+ if uid == None:
+ return 'Euid'
+
+ with TOJAuth.change_current_iden(self._idendesc):
+ ret = self._list_notice(uid, start_index, list_num)
+
+ return ret
+
+ @TOJAuth.check_access(_accessid, TOJAuth.ACCESS_EXECUTE)
+ def _list_notice(self, uid, start_index, list_num):
+ cur = self.db.cursor()
+ sqlstr = ('SELECT "noticeid", "title", "content", "time", '
+ '"noticemodid", "metadata", "unread" FROM "NOTICE" WHERE '
+ '"uid" = %s ORDER BY "noticeid" DESC LIMIT %s OFFSET %s;')
+ sqlarr = (uid, list_num, start_index)
+ cur.execute(sqlstr, sqlarr)
+
+ ret = []
+ for data in cur:
+ obj = {}
+ obj['noticeid'] = data[0]
+ obj['title'] = data[1]
+ obj['content'] = data[2]
+ obj['time'] = data[3]
+ obj['noticemodid'] = data[4]
+ obj['metadata'] = data[5]
+ obj['unread'] = data[6]
+ ret.append(obj)
+
+ self.set_unseen_count(uid, 0)
+
+ return ret
+
+ @imc.async.caller
+ def read_notice(self, noticeid):
+ if(
+ type(noticeid) != int
+ ):
+ return 'Eparameter'
+
+ notice = self.get_notice(noticeid)
+ if notice == None:
+ return 'Enoticeid'
+
+ with TOJAuth.change_current_iden(self._idendesc):
+ self.set_notice_unread(noticeid, False)
+
+ @TOJAuth.check_access(_accessid, TOJAuth.ACCESS_EXECUTE)
+ def set_notice_unread(self, noticeid, unread):
+ cur = self.db.cursor()
+ sqlstr = ('UPDATE "NOTICE" SET "unread" = %s WHERE "noticeid" = %s;')
+ sqlarr = (unread, noticeid)
+ cur.execute(sqlstr, sqlarr)
+
+ @imc.async.caller
+ def get_unseen_count(self):
+ uid = UserMg.get_current_uid()
+ if uid == None:
+ return 'Euid'
+
+ with TOJAuth.change_current_iden(self._idendesc):
+ unseen_count = self._get_unseen_count(uid)
+
+ return {'unseen_count': unseen_count}
+
+ @TOJAuth.check_access(_accessid, TOJAuth.ACCESS_EXECUTE)
+ def _get_unseen_count(self, uid):
+ cur = self.db.cursor()
+ sqlstr = ('SELECT "unseen_count" FROM "NOTICE_UNSEEN" WHERE '
+ '"uid" = %s;')
+ sqlarr = (uid, )
+ cur.execute(sqlstr, sqlarr)
+
+ unseen_count = None
+ for data in cur:
+ unseen_count = data[0]
+
+ return unseen_count
+
+ @TOJAuth.check_access(_accessid, TOJAuth.ACCESS_EXECUTE)
+ def set_unseen_count(self, uid, unseen_count):
+ old_unseen_count = self._get_unseen_count(uid)
+
+ cur = self.db.cursor()
+ sqlstr = ('UPDATE "NOTICE_UNSEEN" SET "unseen_count" = %s WHERE '
+ '"uid" = %s;')
+ sqlarr = (unseen_count, uid)
+ cur.execute(sqlstr, sqlarr)
+
+ if old_unseen_count != unseen_count:
+ self.notify_client(uid)
+
+ @TOJAuth.check_access(_accessid, TOJAuth.ACCESS_EXECUTE)
+ def create_unseen_count(self, uid):
+ cur = self.db.cursor()
+ sqlstr = ('INSERT INTO "NOTICE_UNSEEN" ("uid", "unseen_count") '
+ 'VALUES (%s, %s);')
+ sqlarr = (uid, 0)
+ cur.execute(sqlstr, sqlarr)
+
+ @TOJAuth.check_access(_accessid, TOJAuth.ACCESS_EXECUTE)
+ def notify_client(self, uid):
+ unseen_count = self._get_unseen_count(uid)
+
+ for link in self.get_link('client', uid = uid):
+ Proxy.instance.call_async(
+ link + 'core/notice/', 'update_notice', 10000, None, unseen_count
+ )
+
+ def get_notice(self, noticeid):
+ cur = self.db.cursor()
+ sqlstr = ('SELECT "noticeid", "uid", "title", "content", "time", '
+ '"noticemodid", "metadata", "unread" FROM "NOTICE" WHERE '
+ '"noticeid" = %s;')
+ sqlarr = (noticeid, )
+ cur.execute(sqlstr, sqlarr)
+
+ ret = None
+ for data in cur:
+ ret = {}
+ ret['noticeid'] = data[0]
+ ret['uid'] = data[1]
+ ret['title'] = data[2]
+ ret['content'] = data[3]
+ ret['time'] = data[4]
+ ret['noticemodid'] = data[5]
+ ret['metadata'] = data[6]
+ ret['unread'] = data[7]
+
+ if ret == None:
+ return None
+
+ uid = UserMg.get_current_uid()
+ if uid != ret['uid']:
+ TOJAuth.check_access_func(self._accessid, TOJAuth.ACCESS_EXECUTE)
+
+ return ret
+
+from user import UserMg
diff --git a/src/py/square.py b/src/py/square.py
new file mode 100644
index 0000000..68f1be4
--- /dev/null
+++ b/src/py/square.py
@@ -0,0 +1,311 @@
+from tojauth import TOJAuth
+from asyncdb import AsyncDB
+from user import UserMg
+import imc.proxy
+import config
+
+class SquareMg:
+ _accessid = 4
+
+ TITLE_LEN_MIN = 1
+ TITLE_LEN_MAX = 100
+
+ SQUARE_CATE_NUM_MAX = 50
+
+ def __init__(self, mod_idendesc, get_link_fn):
+ SquareMg.instance = self
+ SquareMg.db = AsyncDB(config.CORE_DBNAME, config.CORE_DBUSER,
+ config.CORE_DBPASSWORD)
+ SquareMg._idendesc = mod_idendesc
+ self.get_link = get_link_fn
+
+ @imc.async.caller
+ def create_square(self, title, hidden, sqmodid, category = []):
+ if(
+ type(title) != str or
+ type(hidden) != bool or
+ type(sqmodid) != int or
+ type(category) != list
+ ):
+ return 'Eparameter'
+
+ for cateid in category:
+ if(
+ type(cateid) != int
+ ):
+ return 'Eparameter'
+
+ if len(title) < self.TITLE_LEN_MIN:
+ return 'Etitle_too_short'
+ elif len(title) > self.TITLE_LEN_MAX:
+ return 'Etitle_too_long'
+
+ if len(category) > self.SQUARE_CATE_NUM_MAX:
+ return 'Etoo_many_category'
+
+ category = list(set(category))
+
+ for cateid in category:
+ if not self.does_cateid_exist(cateid):
+ return 'Eno_such_cateid'
+
+ sqid = self._create_square(title, hidden, sqmodid)
+ self._set_square_category(sqid, category)
+ return {'sqid': sqid}
+
+ @TOJAuth.check_access(_accessid, TOJAuth.ACCESS_CREATE)
+ def _create_square(self, title, hidden, sqmodid):
+ cur = self.db.cursor()
+ sqlstr = ('INSERT INTO "SQUARE" ("title", "hidden", "sqmodid", '
+ '"accessid") VALUES (%s, %s, %s, %s) RETURNING "sqid";')
+ sqlarr = (title, hidden, sqmodid, 0)
+ cur.execute(sqlstr, sqlarr)
+
+ sqid = None
+ for data in cur:
+ sqid = data[0]
+
+ if sqid != None:
+ user_idenid = TOJAuth.get_current_iden()['idenid']
+ with TOJAuth.change_current_iden(self._idendesc):
+ accessid = TOJAuth.instance.create_access(user_idenid)
+
+ sqlstr = ('UPDATE "SQUARE" SET "accessid" = %s WHERE "sqid" = %s;')
+ sqlarr = (accessid, sqid)
+ cur.execute(sqlstr, sqlarr)
+
+ with TOJAuth.change_current_iden(self._idendesc):
+ TOJAuth.instance.set_access_list(
+ accessid, TOJAuth.ROLEID_SQUARE_ADMIN_GROUP,
+ TOJAuth.ACCESS_ALL
+ )
+
+ # sqmod.create_square_data(sqid)
+
+ return sqid;
+
+ @imc.async.caller
+ def delete_square(self, sqid):
+ if(
+ type(sqid) != int
+ ):
+ return 'Eparameter'
+
+ if not self.does_sqid_exist(sqid):
+ return 'Eno_such_sqid'
+
+ self._delete_square(self, sqid)
+
+ def _delete_square(self, sqid):
+ accessid = self.get_accessid_by_sqid(sqid)
+ TOJAuth.check_access_func(accessid, TOJAuth.ACCESS_DELETE)
+
+ # sqmod.delete_square_data(sqid)
+
+ with TOJAuth.change_current_iden(self._idendesc):
+ TOJAuth.instance.del_access(accessid)
+
+ cur = self.db.cursor()
+ sqlstr = ('DELETE FROM "SQUARE" WHERE "sqid" = %s;')
+ sqlarr = (sqid, )
+ cur.execute()
+
+ @imc.async.caller
+ def list_square(self, cateid = None):
+ if(
+ cateid != None and type(cateid) != int
+ ):
+ return 'Eparameter'
+
+ ret = None
+ if cateid == None:
+ ret = self._list_square_all()
+ else:
+ if not self.does_cateid_exist(cateid):
+ return 'Eno_such_cateid'
+ ret = self._list_square_category(cateid)
+
+ return ret
+
+ def _list_square_category(self, cateid):
+ cur = self.db.cursor()
+ sqlstr = ('SELECT "sqid", "title", "start_time", "end_time", "hidden",'
+ ' "sqmodid" FROM "SQUARE" WHERE %s = ANY ("cateid");')
+ sqlarr = (cateid, )
+ cur.execute(sqlstr, sqlarr)
+
+ ret = []
+ for data in cur:
+ obj = {}
+ obj['sqid'] = data[0]
+ obj['title'] = data[1]
+ obj['start_time'] = data[2]
+ obj['end_time'] = data[3]
+ obj['hidden'] = data[4]
+ obj['sqmodid'] = data[5]
+ ret.append(obj)
+
+ return ret
+
+ def _list_square_all(self):
+ cur = self.db.cursor()
+ sqlstr = ('SELECT "sqid", "title", "start_time", "end_time", "hidden",'
+ ' "sqmodid" FROM "SQUARE";')
+ cur.execute(sqlstr)
+
+ ret = []
+ for data in cur:
+ obj = {}
+ obj['sqid'] = data[0]
+ obj['title'] = data[1]
+ obj['start_time'] = data[2]
+ obj['end_time'] = data[3]
+ obj['hidden'] = data[4]
+ obj['sqmodid'] = data[5]
+ ret.append(obj)
+
+ return ret
+
+ @imc.async.caller
+ def create_group():
+ pass
+
+ @imc.async.caller
+ def del_group():
+ pass
+
+ @imc.async.caller
+ def list_group():
+ pass
+
+ @imc.async.caller
+ def group_create_square():
+ pass
+
+ @imc.async.caller
+ def group_remove_square():
+ pass
+
+ @imc.async.caller
+ def group_list_square():
+ pass
+
+ @imc.async.caller
+ def create_category(self, catename):
+ if(
+ type(catename) != str
+ ):
+ return 'Eparameter'
+
+ cateid = self._create_category(catename)
+ return cateid
+
+ @TOJAuth.check_access(_accessid, TOJAuth.ACCESS_CREATE)
+ def _create_category(self, catename):
+ cur = self.db.cursor()
+ sqlstr = ('INSERT INTO "CATEGORY" ("catename") VALUES (%s) RETURNING '
+ '"cateid";')
+ sqlarr = (catename, )
+ cur.execute(sqlstr, sqlarr)
+
+ cateid = None
+ for data in cur:
+ cateid = data[0]
+
+ return cateid
+
+ @imc.async.caller
+ def set_square_category(self, sqid, category):
+ if(
+ type(sqid) != int or
+ type(category) != list
+ ):
+ return 'Eparameter'
+
+ for cateid in category:
+ if(
+ type(cateid) != int
+ ):
+ return 'Eparameter'
+
+ if len(category) > self.SQUARE_CATE_NUM_MAX:
+ return 'Etoo_many_category'
+
+ category = list(set(category))
+
+ if not self.does_sqid_exist(sqid):
+ return 'Eno_such_sqid'
+
+ for cateid in category:
+ if not self.does_cateid_exist(cateid):
+ return 'Eno_such_cateid'
+
+ self._set_square_category(sqid, category)
+
+ def _set_square_category(self, sqid, category):
+ sq_accessid = self.get_accessid_by_sqid(sqid)
+ TOJAuth.check_access_func(sq_accessid, TOJAuth.ACCESS_WRITE)
+
+ cur = self.db.cursor()
+ sqlstr = ('UPDATE "SQUARE" SET "cateid" = %s WHERE "sqid" = %s;')
+ sqlarr = (category, sqid)
+ cur.execute(sqlstr, sqlarr)
+
+ def get_square_info_by_sqid(self, sqid):
+ cur = self.db.cursor()
+ sqlstr = ('SELECT "sqid", "title", "start_time", "end_time", '
+ '"hidden", "sqmodid", "cateid" FROM "SQUARE" WHERE '
+ '"sqid" = %s;')
+ sqlarr = (sqid, )
+ cur.execute(sqlstr, sqlarr)
+
+ ret = None
+ for data in cur:
+ ret = {}
+ ret['sqid'] = data[0]
+ ret['title'] = data[1]
+ ret['start_time'] = data[2]
+ ret['end_time'] = data[3]
+ ret['hidden'] = data[4]
+ ret['sqmodid'] = data[5]
+ ret['cateid'] = data[6]
+
+ return ret
+
+ def does_sqid_exist(self, sqid):
+ ret = self.get_square_info_by_sqid(sqid)
+ return ret != None
+
+ def get_accessid_by_sqid(self, sqid):
+ cur = self.db.cursor()
+ sqlstr = ('SELECT "accessid" FROM "SQUARE" WHERE "sqid" = %s;')
+ sqlarr = (sqid, )
+ cur.execute(sqlstr, sqlarr)
+
+ accessid = None
+ for data in cur:
+ accessid = data[0]
+
+ return accessid
+
+ def get_catename_by_cateid(self, cateid):
+ cur = self.db.cursor()
+ sqlstr = ('SELECT "catename" FROM "CATEGORY" WHERE "cateid" = %s;')
+ sqlarr = (cateid, )
+ cur.execute(sqlstr, sqlarr)
+
+ catename = None
+ for data in cur:
+ catename = data[0]
+
+ return catename
+
+ def does_cateid_exist(self, cateid):
+ catename = self.get_catename_by_cateid(cateid)
+ return catename != None
+
+class Square:
+ pass
+
+class Group:
+ pass
diff --git a/src/py/user.py b/src/py/user.py
index 3c58c03..33c2c6c 100755
--- a/src/py/user.py
+++ b/src/py/user.py
@@ -22,6 +22,8 @@ class UserMg:
AVATAR_LEN_MAX = 200
ABOUTME_LEN_MIN = 0
ABOUTME_LEN_MAX = 1000
+ COVER_LEN_MIN = 0
+ COVER_LEN_MAX = 200
def __init__(self, mod_idendesc, get_link_fn):
UserMg.instance = self
@@ -40,16 +42,21 @@ class UserMg:
'core/user/', 'get_user_info', self.get_user_info)
Proxy.instance.register_call(
'core/user/', 'set_user_info', self.set_user_info)
+ Proxy.instance.register_call(
+ 'core/user/', 'change_user_password', self.change_user_password)
@imc.async.caller
- def register(self, username, password, nickname, email, avatar, aboutme):
+ def register(
+ self, username, password, nickname, email, avatar, aboutme, cover
+ ):
if(
type(username) != str or
type(password) != str or
type(nickname) != str or
type(email) != str or
type(avatar) != str or
- type(aboutme) != str
+ type(aboutme) != str or
+ type(cover) != str
):
return 'Eparameter'
@@ -77,32 +84,44 @@ class UserMg:
return 'Eaboutme_too_short'
elif len(aboutme) > self.ABOUTME_LEN_MAX:
return 'Eaboutme_too_long'
+ elif len(cover) < self.COVER_LEN_MIN:
+ return 'Ecover_too_short'
+ elif len(cover) > self.COVER_LEN_MAX:
+ return 'Ecover_too_long'
passhash = self._password_hash(password)
with TOJAuth.change_current_iden(self._idendesc):
try:
uid = self._create_user(
- username, passhash, nickname, email, avatar, aboutme)
+ username, passhash, nickname, email, avatar, aboutme, cover
+ )
except psycopg2.IntegrityError:
return 'Eusername_exists'
return {'uid' : uid}
@TOJAuth.check_access(_accessid, TOJAuth.ACCESS_EXECUTE)
- def _create_user(self, username, passhash, nickname, email, avatar,
- aboutme):
+ def _create_user(
+ self, username, passhash, nickname, email, avatar, aboutme, cover
+ ):
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)
+ '"email", "avatar", "aboutme", "cover", "idenid") '
+ 'VALUES (%s, %s, %s, %s, %s, %s, %s, %s) RETURNING "uid";')
+ sqlarr = (
+ username, passhash, nickname, email, avatar, aboutme, cover, roleid
+ )
cur.execute(sqlstr, sqlarr)
for data in cur:
uid = data[0]
+
+ with TOJAuth.change_current_iden(self._idendesc):
+ Notice.instance.create_unseen_count(uid)
+
return uid
@imc.async.caller
@@ -130,13 +149,14 @@ class UserMg:
idenid = data[0]
if idenid == None:
- return 'Elogin_faild'
+ return 'Elogin_failed'
+ client_link = TOJAuth.get_current_iden()['link']
with TOJAuth.change_current_iden(self._idendesc):
stat,data = Proxy.instance.call(self.get_link('center'),
'create_iden',
10000,
- TOJAuth.get_current_iden()['link'],
+ client_link,
idenid,
TOJAuth.ROLETYPE_USER,
{'uid' : uid})
@@ -178,11 +198,12 @@ class UserMg:
if real_uphash != uphash:
return 'Elogin_failed'
+ client_link = TOJAuth.get_current_iden()['link']
with TOJAuth.change_current_iden(self._idendesc):
stat,data = Proxy.instance.call(self.get_link('center'),
'create_iden',
10000,
- TOJAuth.get_current_iden()['link'],
+ client_link,
idenid,
TOJAuth.ROLETYPE_USER,
{'uid' : uid})
@@ -212,13 +233,14 @@ class UserMg:
return ret
@imc.async.caller
- def set_user_info(self, uid, nickname, email, avatar, aboutme):
+ def set_user_info(self, uid, nickname, email, avatar, aboutme, cover):
if(
type(uid) != int or
type(nickname) != str or
type(email) != str or
type(avatar) != str or
- type(aboutme) != str
+ type(aboutme) != str or
+ type(cover) != str
):
return 'Eparameter'
@@ -238,6 +260,10 @@ class UserMg:
return 'Eaboutme_too_short'
elif len(aboutme) > self.ABOUTME_LEN_MAX:
return 'Eaboutme_too_long'
+ elif len(cover) < self.COVER_LEN_MIN:
+ return 'Ecover_too_short'
+ elif len(cover) > self.COVER_LEN_MAX:
+ return 'Ecover_too_long'
idenid = self.get_idenid_by_uid(uid)
if idenid == None:
@@ -249,8 +275,9 @@ class UserMg:
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)
+ '"avatar" = %s, "aboutme" = %s, "cover" = %s WHERE '
+ '"uid" = %s;')
+ sqlarr = (nickname, email, avatar, aboutme, cover, uid)
cur.execute(sqlstr, sqlarr)
@imc.async.caller
@@ -310,7 +337,8 @@ class UserMg:
def get_user_info_by_uid(self, uid):
cur = self.db.cursor()
- sqlstr = ('SELECT * FROM "USER" WHERE "uid" = %s;')
+ sqlstr = ('SELECT "uid", "username", "nickname", "email", "avatar", '
+ '"aboutme", "cover" FROM "USER" WHERE "uid" = %s;')
sqlarr = (uid, )
cur.execute(sqlstr, sqlarr)
@@ -319,10 +347,11 @@ class UserMg:
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]
+ ret['nickname'] = data[2]
+ ret['email'] = data[3]
+ ret['avatar'] = data[4]
+ ret['aboutme'] = data[5]
+ ret['cover'] = data[6]
return ret
@@ -374,3 +403,6 @@ def load(mod_idendesc, get_link_fn):
def unload():
pass
+
+from notice import Notice
+