[PATCH 1/3] create a new login page

From: ShaoHe Feng <shaohef@linux.vnet.ibm.com> this page is used for the session timeout or first login. Signed-off-by: ShaoHe Feng <shaohef@linux.vnet.ibm.com> Signed-off-by: Yu Xin Huo <huoyuxin@linux.vnet.ibm.com> --- ui/images/progressing.gif | Bin 0 -> 1152 bytes ui/pages/login.html.tmpl | 247 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 247 insertions(+) create mode 100644 ui/images/progressing.gif create mode 100644 ui/pages/login.html.tmpl diff --git a/ui/images/progressing.gif b/ui/images/progressing.gif new file mode 100644 index 0000000000000000000000000000000000000000..6552d41d9d4c874091bb51931c6adf64a95e8bd0 GIT binary patch literal 1152 zcmZ?wbhEHb6k!ly*v!E2|NsBHckiA#b7s?~O&uK_IXO9@p`oUxrgCy}4A_9;e{Mh5 zkYH!W09PYD17=2`8pWS1oFWVy3_2k7AY&O=+5}E^`WY^hIhD@I;2`qkhUamCHs#2? zD{Sl5ddqAu;o;E8n07H&VTOd$9w+z3Od8dz)1OOlg@hfQ?6P6gg)Nhut~h8s_iHy| zTx?f<DfNuF4qs+in1T70o7P)P87f1<g5(0~t-`bz%`;<c7;R*Hby&0+Cd*D$nyx)7 zxH>hoEs9-2GEYbl<TO?^r*$AZO&~F#<dR{_!xK!0-EtLPZ*p|yWoF`%>SmZA?aQ<9 zUT3kA$h=8X2{%vLaEeZ2FfFvxHCy+@)2xTXXx&nW19L8~I4mhFCLSR*N5YUN_g8RC zxvG$d3rC2Yoni>Hr8Z+mk+UtMt&Fyriq3S|nYyz*lh|s_)v7fmBnyPWjzbSOeSwpn ztM^*GK3gr@WX{W=;H4@s$Eix`o#&Z+UC|vq;?Mm$*qz>q{MpOLKD$V>lW^GM@gRp< zTfqAxmTMW#NQtz1Ow(GUENaLTnG@~OSSl%)a-~@^*=_L^Wu6LazRZG$dI^iu%U-z% zg<00g*_8=1ySk){v9Pk(*~<9qvQD2qQDdsojG1{NY_a__TQemj7eK-u-Fqm>f>utm zWMS=L&jJU059@Suul#8<RCK0juuU^pO9X~|9`=wYHdzoCYCehQmh?GGSt;IO&EY61 z^|cU^WKC}pQa3GC)^bS)J5HFrADAqr$@=Tg_KIeUMR6Q@nr+9QW_y9zNsLj!T)@YO zmFW>EN`0IXPrZ>S5M3ptD%hrTMQhc8T>+_g4tF#}E)IMpc<k8J3C>bEce!tTI4V-^ zEEL|{;B8wW%<SUK!k*>CYhksVX{CWv466RGb|aXRcN%49rjY*aHrnWY;d4a(eT< sn9_<U58lHODbH9KGQC;#6@s@G?AG7t-SQycLr1Fr#FC=U9tH+$0KoWQ9smFU literal 0 HcmV?d00001 diff --git a/ui/pages/login.html.tmpl b/ui/pages/login.html.tmpl new file mode 100644 index 0000000..e7afbb3 --- /dev/null +++ b/ui/pages/login.html.tmpl @@ -0,0 +1,247 @@ +#* + * Project Kimchi + * + * Copyright IBM, Corp. 2014 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *# +#unicode UTF-8 +#import gettext +#from kimchi.cachebust import href +#silent t = gettext.translation($lang.domain, $lang.localedir, languages=$lang.lang) +#silent _ = t.gettext +#silent _t = t.gettext +#from kimchi.config import get_version +<!DOCTYPE html> +<html lang="$lang.lang[0]"> +<head> +<meta charset="UTF-8"> +<title>Kimchi</title> +<meta http-equiv="X-UA-Compatible" content="IE=edge"/> +<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" /> + +<style type="text/css"> +.login { + font-family: Arial; + margin: 0px; +} + +.login input.invalid-field { + border-color: #C85305 !important; +} + +.login .header { + background: none repeat scroll 0 0 #353D40; + border-bottom: 3px solid #008ABF; + border-top: 0 none; + box-shadow: 0 0 2px rgba(0, 0, 0, 0.5); + height: 50px; + color: #F8F8F8; + font-size: 13px; + font-weight: 700; + font-family: Helvetica; + overflow: hidden; +} + +.login .header .lang { + float: right; + margin-right: 20px; + margin-top: 14px; +} + +.login .header .lang select { + vertical-align: middle; +} + +.login .content-pane { + margin-left: auto; + margin-right: auto; + margin-top: 200px; + width: 260px; +} + +.login .content-pane .trademark { + margin-bottom: 30px; +} + +.login .content-pane .trademark .logo { + background: url("../images/logo.ico") no-repeat scroll center center transparent; + display: inline-block; + height: 25px; + width: 25px; + margin-left: -4px; + margin-right: 5px; + vertical-align: middle; +} + +.login .content-pane .trademark .name { + vertical-align: middle; + padding-top: 2px; + font-weight: bold; + font-size: 18px; +} + +.login .content-pane .trademark .version { + vertical-align: middle; + padding-top: 6px; + font-size: 13px; + padding-left: 6px; +} + +.login .content-pane .message-area .item { + font-size: 12px; + margin-bottom: 30px; + margin-top: 30px; + height: 20px; +} + +.login .content-pane .message-area .text { + color: #C85305; +} + +.login .progress-indicator .progress-icon { + margin-right: 3px; + vertical-align: middle; + width: 15px; + height: 15px; +} + +.login .progress-indicator .progress-text { + vertical-align: middle; + padding-top: 2px; +} + +.login .content-pane .hint { + margin-bottom: 10px; + font-size: 14px; +} + +.login .content-pane .field-area { + overflow: hidden; +} + +.login .content-pane .field-area .text-field { + width: 240px; + padding: 5px 7px; + margin-bottom: 5px; + border: 1px solid #BABABA; + border-radius: 1px; +} + +.login .button { + margin-top: 20px; + background: -moz-linear-gradient(center top , #1783BF 0%, #0C4C88 100%) repeat scroll 0 0 transparent; + border-color: #666666 #666666 #555555; + border-image: none; + border-radius: 5px 5px 5px 5px; + border-style: solid; + border-width: 1px; + color: #DDDDDD; + cursor: pointer; + font-weight: bolder; + padding: 5px 10px; + float: right; +} +</style> + +<script> + +function validateForm() { + var user = document.forms["login"]["username"]; + var pass = document.forms["login"]["password"]; + var validateField = function(field){ + field.className = "text-field"; + var isValid = field.value && field.value.trim()!="" ? true : false; + if(!isValid) field.className += " invalid-field"; + return isValid; + }; + var isValid = validateField(user); + isValid = validateField(pass) && isValid; + if(isValid) + document.getElementById("messWait").style.display = ""; + return isValid; +} + +function getCookie(cname) { + var name = cname + "="; + var ca = document.cookie.split(';'); + for(var i=0; i<ca.length; i++) { + var c = ca[i].trim(); + if (c.indexOf(name)==0) return c.substring(name.length,c.length); + } + return null; +} + +function setCookie(cname,cvalue,exdays) { + var d = new Date(); + d.setTime(d.getTime()+(exdays*24*60*60*1000)); + var expires = "expires="+d.toGMTString(); + document.cookie = cname + "=" + cvalue + "; " + expires; +} + +function init() { + var defaultLang = 'en_US'; + var clientLang = document.getElementById('userLang').value; + var persistLang = getCookie('kimchiLang'); + document.getElementById("userLang").value = persistLang || clientLang || defaultLang; +/* + var url = window.location.href; + if(url.indexOf("wrongUserPass")!=-1) + document.getElementById("messUserPass").style.display = ""; + if(url.indexOf("sessionTimeout")!=-1) + document.getElementById("messSession").style.display = ""; +*/ +} + +function changeLang() { + var lang = document.getElementById('userLang').value; + setCookie('kimchiLang', lang, 365); + window.location.reload(); +} + +</script> +</head> +<body class="login" onload="init()"> + +<div class="header"> + <div class="lang"> + <label>$_("Language"):</label> + <select id="userLang" onchange="changeLang()"> + <option value="en_US">English (US)</option> + <option value="zh_CN">中文(简体)</option> + <option value="pt_BR">Português (Brasil)</option> + </select> + </div> +</div> +<div class="content-pane"> + <div class="trademark"><span class="logo"></span><span class="name">Kimchi</span><span class="version">1.2</span></div> + <div class="message-area"> + <div id="messUserPass" class="item text" style="display: none;">$_("User Name or password is incorrect.")</div> + <div id="messSession" class="item text" style="display: none;">$_("Session timeout, please re-login.")</div> + <div id="messWait" class="item progress-indicator" style="display: none;"> + <img src="images/progressing.gif" class="progress-icon"><span class="progress-text">$_("Processing")...</span> + </div> + </div> + <div class="hint">$_("Sign in with your linux account")</div> + <div class="field-area"> + <form name="login" action="/login?next=$getVar('data.next', '/')" method="POST" onsubmit="return validateForm()"> + <input type="hidden" name="next" value="$getVar('data.next', '/')"> + <input type="text" name="username" placeholder="$_("User Name")" class="text-field" autofocus> + <input type="password" name="password" placeholder="$_("Password")" class="text-field"> + <input type="submit" value="$_("Sign In")" class="button"> + </form> + </div> +</div> + +</body> +</html> -- 1.9.3

From: ShaoHe Feng <shaohef@linux.vnet.ibm.com> If the content type is application/json still raise 401 status code. And let UI redirect to login page. or the backe redirects to login page directly. Signed-off-by: ShaoHe Feng <shaohef@linux.vnet.ibm.com> Signed-off-by: Yu Xin Huo <huoyuxin@linux.vnet.ibm.com> --- src/kimchi/auth.py | 10 ++++++++++ src/kimchi/config.py.in | 3 +++ src/kimchi/root.py | 28 +++++++++++++++++++--------- ui/js/src/kimchi.main.js | 5 +---- 4 files changed, 33 insertions(+), 13 deletions(-) diff --git a/src/kimchi/auth.py b/src/kimchi/auth.py index dc78ded..0e4fab9 100644 --- a/src/kimchi/auth.py +++ b/src/kimchi/auth.py @@ -28,6 +28,7 @@ import re import termios import time +import urllib2 from kimchi import template @@ -41,6 +42,11 @@ REFRESH = 'robot-refresh' +def redirect_login(): + next_url = urllib2.quote( + cherrypy.request.path_info.encode('utf-8'), safe="") + raise cherrypy.HTTPRedirect("/login.html?next=%s" % next_url, 303) + def debug(msg): pass # cherrypy.log.error(msg) @@ -234,6 +240,10 @@ def kimchiauth(admin_methods=None): raise cherrypy.HTTPError(403) return + # not a REST full request, redirect login page directly + if not template.can_accept('application/json'): + redirect_login() + if not from_browser(): cherrypy.response.headers['WWW-Authenticate'] = 'Basic realm=kimchi' diff --git a/src/kimchi/config.py.in b/src/kimchi/config.py.in index 0206570..d4cbda0 100644 --- a/src/kimchi/config.py.in +++ b/src/kimchi/config.py.in @@ -187,6 +187,9 @@ class KimchiConfig(dict): '/spice.html': { 'tools.kimchiauth.on': True }, + '/kimchi-ui.html': { + 'tools.kimchiauth.on': True + }, '/data/screenshots': { 'tools.staticdir.on': True, 'tools.staticdir.dir': get_screenshot_path(), diff --git a/src/kimchi/root.py b/src/kimchi/root.py index 8b1d09b..181ab13 100644 --- a/src/kimchi/root.py +++ b/src/kimchi/root.py @@ -81,7 +81,7 @@ def get(self): @cherrypy.expose def default(self, page, **kwargs): if page.endswith('.html'): - return template.render(page, None) + return template.render(page, kwargs) raise cherrypy.HTTPError(404) @cherrypy.expose @@ -110,14 +110,24 @@ def __init__(self, model, dev_env): self.messages = messages @cherrypy.expose - def login(self, *args): - params = parse_request() - try: - username = params['username'] - password = params['password'] - except KeyError, item: - e = MissingParameter('KCHAUTH0003E', {'item': str(item)}) - raise cherrypy.HTTPError(400, e.message) + def login(self, *args, **kwargs): + username = kwargs.get('username') + password = kwargs.get('password') + # forms base authentication + if username is not None: + # UI can pass the redirect url by "next" query parameter + next_url = kwargs.get('next', "/") + next_url = type(next_url) is list and next_url[0] + auth.login(username, password) + raise cherrypy.HTTPRedirect(next_url, 303) + else: + try: + params = parse_request() + username = params['username'] + password = params['password'] + except KeyError, item: + e = MissingParameter('KCHAUTH0003E', {'item': str(item)}) + raise cherrypy.HTTPError(400, e.message) try: user_info = auth.login(username, password) diff --git a/ui/js/src/kimchi.main.js b/ui/js/src/kimchi.main.js index 86fed5b..1d614a5 100644 --- a/ui/js/src/kimchi.main.js +++ b/ui/js/src/kimchi.main.js @@ -227,10 +227,7 @@ kimchi.main = function() { kimchi.previousAjax = ajaxSettings; $(".empty-when-logged-off").empty(); $(".remove-when-logged-off").remove(); - kimchi.window.open({ - url: 'login-window.html', - id: 'login-window-wrapper' - }); + document.location.href='login.html'; return; } else if((jqXHR['status'] == 0) && ("error"==jqXHR.statusText)) { -- 1.9.3

From: ShaoHe Feng <shaohef@linux.vnet.ibm.com> let cookie remember the last page. Signed-off-by: ShaoHe Feng <shaohef@linux.vnet.ibm.com> Signed-off-by: Yu Xin Huo <huoyuxin@linux.vnet.ibm.com> --- src/kimchi/root.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/kimchi/root.py b/src/kimchi/root.py index 181ab13..651c847 100644 --- a/src/kimchi/root.py +++ b/src/kimchi/root.py @@ -93,7 +93,11 @@ def tabs(self, page, **kwargs): data['ui_dir'] = paths.ui_dir if page.endswith('.html'): - return template.render('tabs/' + page, data) + context = template.render('tabs/' + page, data) + cherrypy.response.cookie[ + "lastPage"] = "/#tabs/" + page.rstrip(".html") + cherrypy.response.cookie['lastPage']['path'] = '/' + return context raise cherrypy.HTTPError(404) @@ -115,9 +119,13 @@ def login(self, *args, **kwargs): password = kwargs.get('password') # forms base authentication if username is not None: - # UI can pass the redirect url by "next" query parameter - next_url = kwargs.get('next', "/") - next_url = type(next_url) is list and next_url[0] + next_url = cherrypy.request.cookie.get("lastPage") + if next_url is None: + # UI can pass the redirect url by "next" query parameter + next_url = kwargs.get('next', "/") + next_url = type(next_url) is list and next_url[0] + else: + next_url = next_url.value auth.login(username, password) raise cherrypy.HTTPRedirect(next_url, 303) else: -- 1.9.3

tested, see issues below: 1. I always see the kimchi UI tabs before login page, as it is server side re-direct, why kimchi tabs appear? 2. when username or password is wrong, it is directed to an error page with content below, it should be back to login page with an error message. /ERROR CODE/ // // /500 Internal Server Error/ // /REASON/ // /The server encountered an unexpected condition which prevented it from fulfilling the request./ // /STACK/ // // /Traceback (most recent call last): File "/usr/lib/python2.6/site-packages/cherrypy/_cprequest.py", line 656, in respond response.body = self.handler() File "/usr/lib/python2.6/site-packages/cherrypy/lib/encoding.py", line 188, in __call__ self.body = self.oldhandler(*args, **kwargs) File "/usr/lib/python2.6/site-packages/cherrypy/_cpdispatch.py", line 34, in __call__ return self.callable(*self.args, **self.kwargs) File "/root/kimchi-repo/test/kimchi/src/kimchi/root.py", line 129, in login auth.login(username, password) File "/root/kimchi-repo/test/kimchi/src/kimchi/auth.py", line 198, in login if not authenticate(username, password): File "/root/kimchi-repo/test/kimchi/src/kimchi/auth.py", line 135, in authenticate raise OperationFailed("KCHAUTH0001E", msg_args) OperationFailed: KCHAUTH0001E: Authentication failed for user 'root'. [Error code: 7]/ On 5/31/2014 1:16 AM, shaohef@linux.vnet.ibm.com wrote:
From: ShaoHe Feng <shaohef@linux.vnet.ibm.com>
this page is used for the session timeout or first login.
Signed-off-by: ShaoHe Feng <shaohef@linux.vnet.ibm.com> Signed-off-by: Yu Xin Huo <huoyuxin@linux.vnet.ibm.com> --- ui/images/progressing.gif | Bin 0 -> 1152 bytes ui/pages/login.html.tmpl | 247 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 247 insertions(+) create mode 100644 ui/images/progressing.gif create mode 100644 ui/pages/login.html.tmpl
diff --git a/ui/images/progressing.gif b/ui/images/progressing.gif new file mode 100644 index 0000000000000000000000000000000000000000..6552d41d9d4c874091bb51931c6adf64a95e8bd0 GIT binary patch literal 1152 zcmZ?wbhEHb6k!ly*v!E2|NsBHckiA#b7s?~O&uK_IXO9@p`oUxrgCy}4A_9;e{Mh5 zkYH!W09PYD17=2`8pWS1oFWVy3_2k7AY&O=+5}E^`WY^hIhD@I;2`qkhUamCHs#2? zD{Sl5ddqAu;o;E8n07H&VTOd$9w+z3Od8dz)1OOlg@hfQ?6P6gg)Nhut~h8s_iHy| zTx?f<DfNuF4qs+in1T70o7P)P87f1<g5(0~t-`bz%`;<c7;R*Hby&0+Cd*D$nyx)7 zxH>hoEs9-2GEYbl<TO?^r*$AZO&~F#<dR{_!xK!0-EtLPZ*p|yWoF`%>SmZA?aQ<9 zUT3kA$h=8X2{%vLaEeZ2FfFvxHCy+@)2xTXXx&nW19L8~I4mhFCLSR*N5YUN_g8RC zxvG$d3rC2Yoni>Hr8Z+mk+UtMt&Fyriq3S|nYyz*lh|s_)v7fmBnyPWjzbSOeSwpn ztM^*GK3gr@WX{W=;H4@s$Eix`o#&Z+UC|vq;?Mm$*qz>q{MpOLKD$V>lW^GM@gRp< zTfqAxmTMW#NQtz1Ow(GUENaLTnG@~OSSl%)a-~@^*=_L^Wu6LazRZG$dI^iu%U-z% zg<00g*_8=1ySk){v9Pk(*~<9qvQD2qQDdsojG1{NY_a__TQemj7eK-u-Fqm>f>utm zWMS=L&jJU059@Suul#8<RCK0juuU^pO9X~|9`=wYHdzoCYCehQmh?GGSt;IO&EY61 z^|cU^WKC}pQa3GC)^bS)J5HFrADAqr$@=Tg_KIeUMR6Q@nr+9QW_y9zNsLj!T)@YO zmFW>EN`0IXPrZ>S5M3ptD%hrTMQhc8T>+_g4tF#}E)IMpc<k8J3C>bEce!tTI4V-^ zEEL|{;B8wW%<SUK!k*>CYhksVX{CWv466RGb|aXRcN%49rjY*aHrnWY;d4a(eT< sn9_<U58lHODbH9KGQC;#6@s@G?AG7t-SQycLr1Fr#FC=U9tH+$0KoWQ9smFU
literal 0 HcmV?d00001
diff --git a/ui/pages/login.html.tmpl b/ui/pages/login.html.tmpl new file mode 100644 index 0000000..e7afbb3 --- /dev/null +++ b/ui/pages/login.html.tmpl @@ -0,0 +1,247 @@ +#* + * Project Kimchi + * + * Copyright IBM, Corp. 2014 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *# +#unicode UTF-8 +#import gettext +#from kimchi.cachebust import href +#silent t = gettext.translation($lang.domain, $lang.localedir, languages=$lang.lang) +#silent _ = t.gettext +#silent _t = t.gettext +#from kimchi.config import get_version +<!DOCTYPE html> +<html lang="$lang.lang[0]"> +<head> +<meta charset="UTF-8"> +<title>Kimchi</title> +<meta http-equiv="X-UA-Compatible" content="IE=edge"/> +<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" /> + +<style type="text/css"> +.login { + font-family: Arial; + margin: 0px; +} + +.login input.invalid-field { + border-color: #C85305 !important; +} + +.login .header { + background: none repeat scroll 0 0 #353D40; + border-bottom: 3px solid #008ABF; + border-top: 0 none; + box-shadow: 0 0 2px rgba(0, 0, 0, 0.5); + height: 50px; + color: #F8F8F8; + font-size: 13px; + font-weight: 700; + font-family: Helvetica; + overflow: hidden; +} + +.login .header .lang { + float: right; + margin-right: 20px; + margin-top: 14px; +} + +.login .header .lang select { + vertical-align: middle; +} + +.login .content-pane { + margin-left: auto; + margin-right: auto; + margin-top: 200px; + width: 260px; +} + +.login .content-pane .trademark { + margin-bottom: 30px; +} + +.login .content-pane .trademark .logo { + background: url("../images/logo.ico") no-repeat scroll center center transparent; + display: inline-block; + height: 25px; + width: 25px; + margin-left: -4px; + margin-right: 5px; + vertical-align: middle; +} + +.login .content-pane .trademark .name { + vertical-align: middle; + padding-top: 2px; + font-weight: bold; + font-size: 18px; +} + +.login .content-pane .trademark .version { + vertical-align: middle; + padding-top: 6px; + font-size: 13px; + padding-left: 6px; +} + +.login .content-pane .message-area .item { + font-size: 12px; + margin-bottom: 30px; + margin-top: 30px; + height: 20px; +} + +.login .content-pane .message-area .text { + color: #C85305; +} + +.login .progress-indicator .progress-icon { + margin-right: 3px; + vertical-align: middle; + width: 15px; + height: 15px; +} + +.login .progress-indicator .progress-text { + vertical-align: middle; + padding-top: 2px; +} + +.login .content-pane .hint { + margin-bottom: 10px; + font-size: 14px; +} + +.login .content-pane .field-area { + overflow: hidden; +} + +.login .content-pane .field-area .text-field { + width: 240px; + padding: 5px 7px; + margin-bottom: 5px; + border: 1px solid #BABABA; + border-radius: 1px; +} + +.login .button { + margin-top: 20px; + background: -moz-linear-gradient(center top , #1783BF 0%, #0C4C88 100%) repeat scroll 0 0 transparent; + border-color: #666666 #666666 #555555; + border-image: none; + border-radius: 5px 5px 5px 5px; + border-style: solid; + border-width: 1px; + color: #DDDDDD; + cursor: pointer; + font-weight: bolder; + padding: 5px 10px; + float: right; +} +</style> + +<script> + +function validateForm() { + var user = document.forms["login"]["username"]; + var pass = document.forms["login"]["password"]; + var validateField = function(field){ + field.className = "text-field"; + var isValid = field.value && field.value.trim()!="" ? true : false; + if(!isValid) field.className += " invalid-field"; + return isValid; + }; + var isValid = validateField(user); + isValid = validateField(pass) && isValid; + if(isValid) + document.getElementById("messWait").style.display = ""; + return isValid; +} + +function getCookie(cname) { + var name = cname + "="; + var ca = document.cookie.split(';'); + for(var i=0; i<ca.length; i++) { + var c = ca[i].trim(); + if (c.indexOf(name)==0) return c.substring(name.length,c.length); + } + return null; +} + +function setCookie(cname,cvalue,exdays) { + var d = new Date(); + d.setTime(d.getTime()+(exdays*24*60*60*1000)); + var expires = "expires="+d.toGMTString(); + document.cookie = cname + "=" + cvalue + "; " + expires; +} + +function init() { + var defaultLang = 'en_US'; + var clientLang = document.getElementById('userLang').value; + var persistLang = getCookie('kimchiLang'); + document.getElementById("userLang").value = persistLang || clientLang || defaultLang; +/* + var url = window.location.href; + if(url.indexOf("wrongUserPass")!=-1) + document.getElementById("messUserPass").style.display = ""; + if(url.indexOf("sessionTimeout")!=-1) + document.getElementById("messSession").style.display = ""; +*/ +} + +function changeLang() { + var lang = document.getElementById('userLang').value; + setCookie('kimchiLang', lang, 365); + window.location.reload(); +} + +</script> +</head> +<body class="login" onload="init()"> + +<div class="header"> + <div class="lang"> + <label>$_("Language"):</label> + <select id="userLang" onchange="changeLang()"> + <option value="en_US">English (US)</option> + <option value="zh_CN">中文(简体)</option> + <option value="pt_BR">Português (Brasil)</option> + </select> + </div> +</div> +<div class="content-pane"> + <div class="trademark"><span class="logo"></span><span class="name">Kimchi</span><span class="version">1.2</span></div> + <div class="message-area"> + <div id="messUserPass" class="item text" style="display: none;">$_("User Name or password is incorrect.")</div> + <div id="messSession" class="item text" style="display: none;">$_("Session timeout, please re-login.")</div> + <div id="messWait" class="item progress-indicator" style="display: none;"> + <img src="images/progressing.gif" class="progress-icon"><span class="progress-text">$_("Processing")...</span> + </div> + </div> + <div class="hint">$_("Sign in with your linux account")</div> + <div class="field-area"> + <form name="login" action="/login?next=$getVar('data.next', '/')" method="POST" onsubmit="return validateForm()"> + <input type="hidden" name="next" value="$getVar('data.next', '/')"> + <input type="text" name="username" placeholder="$_("User Name")" class="text-field" autofocus> + <input type="password" name="password" placeholder="$_("Password")" class="text-field"> + <input type="submit" value="$_("Sign In")" class="button"> + </form> + </div> +</div> + +</body> +</html>

On 6/3/2014 11:30 AM, Yu Xin Huo wrote:
tested, see issues below:
1. I always see the kimchi UI tabs before login page, as it is server side re-direct, why kimchi tabs appear?
2. when username or password is wrong, it is directed to an error page with content below, it should be back to login page with an error message.
/ERROR CODE/
// // /500 Internal Server Error/ //
/REASON/
// /The server encountered an unexpected condition which prevented it from fulfilling the request./ //
/STACK/
// // /Traceback (most recent call last): File "/usr/lib/python2.6/site-packages/cherrypy/_cprequest.py", line 656, in respond response.body = self.handler() File "/usr/lib/python2.6/site-packages/cherrypy/lib/encoding.py", line 188, in __call__ self.body = self.oldhandler(*args, **kwargs) File "/usr/lib/python2.6/site-packages/cherrypy/_cpdispatch.py", line 34, in __call__ return self.callable(*self.args, **self.kwargs) File "/root/kimchi-repo/test/kimchi/src/kimchi/root.py", line 129, in login auth.login(username, password) File "/root/kimchi-repo/test/kimchi/src/kimchi/auth.py", line 198, in login if not authenticate(username, password): File "/root/kimchi-repo/test/kimchi/src/kimchi/auth.py", line 135, in authenticate raise OperationFailed("KCHAUTH0001E", msg_args) OperationFailed: KCHAUTH0001E: Authentication failed for user 'root'. [Error code: 7]/ /3. there need to be message about "login fail" and "session timeout", need backend API available on html page to get the message./
On 5/31/2014 1:16 AM, shaohef@linux.vnet.ibm.com wrote:
From: ShaoHe Feng<shaohef@linux.vnet.ibm.com>
this page is used for the session timeout or first login.
Signed-off-by: ShaoHe Feng<shaohef@linux.vnet.ibm.com> Signed-off-by: Yu Xin Huo<huoyuxin@linux.vnet.ibm.com> --- ui/images/progressing.gif | Bin 0 -> 1152 bytes ui/pages/login.html.tmpl | 247 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 247 insertions(+) create mode 100644 ui/images/progressing.gif create mode 100644 ui/pages/login.html.tmpl
diff --git a/ui/images/progressing.gif b/ui/images/progressing.gif new file mode 100644 index 0000000000000000000000000000000000000000..6552d41d9d4c874091bb51931c6adf64a95e8bd0 GIT binary patch literal 1152 zcmZ?wbhEHb6k!ly*v!E2|NsBHckiA#b7s?~O&uK_IXO9@p`oUxrgCy}4A_9;e{Mh5 zkYH!W09PYD17=2`8pWS1oFWVy3_2k7AY&O=+5}E^`WY^hIhD@I;2`qkhUamCHs#2? zD{Sl5ddqAu;o;E8n07H&VTOd$9w+z3Od8dz)1OOlg@hfQ?6P6gg)Nhut~h8s_iHy| zTx?f<DfNuF4qs+in1T70o7P)P87f1<g5(0~t-`bz%`;<c7;R*Hby&0+Cd*D$nyx)7 zxH>hoEs9-2GEYbl<TO?^r*$AZO&~F#<dR{_!xK!0-EtLPZ*p|yWoF`%>SmZA?aQ<9 zUT3kA$h=8X2{%vLaEeZ2FfFvxHCy+@)2xTXXx&nW19L8~I4mhFCLSR*N5YUN_g8RC zxvG$d3rC2Yoni>Hr8Z+mk+UtMt&Fyriq3S|nYyz*lh|s_)v7fmBnyPWjzbSOeSwpn ztM^*GK3gr@WX{W=;H4@s$Eix`o#&Z+UC|vq;?Mm$*qz>q{MpOLKD$V>lW^GM@gRp< zTfqAxmTMW#NQtz1Ow(GUENaLTnG@~OSSl%)a-~@^*=_L^Wu6LazRZG$dI^iu%U-z% zg<00g*_8=1ySk){v9Pk(*~<9qvQD2qQDdsojG1{NY_a__TQemj7eK-u-Fqm>f>utm zWMS=L&jJU059@Suul#8<RCK0juuU^pO9X~|9`=wYHdzoCYCehQmh?GGSt;IO&EY61 z^|cU^WKC}pQa3GC)^bS)J5HFrADAqr$@=Tg_KIeUMR6Q@nr+9QW_y9zNsLj!T)@YO zmFW>EN`0IXPrZ>S5M3ptD%hrTMQhc8T>+_g4tF#}E)IMpc<k8J3C>bEce!tTI4V-^ zEEL|{;B8wW%<SUK!k*>CYhksVX{CWv466RGb|aXRcN%49rjY*aHrnWY;d4a(eT< sn9_<U58lHODbH9KGQC;#6@s@G?AG7t-SQycLr1Fr#FC=U9tH+$0KoWQ9smFU
literal 0 HcmV?d00001
diff --git a/ui/pages/login.html.tmpl b/ui/pages/login.html.tmpl new file mode 100644 index 0000000..e7afbb3 --- /dev/null +++ b/ui/pages/login.html.tmpl @@ -0,0 +1,247 @@ +#* + * Project Kimchi + * + * Copyright IBM, Corp. 2014 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *# +#unicode UTF-8 +#import gettext +#from kimchi.cachebust import href +#silent t = gettext.translation($lang.domain, $lang.localedir, languages=$lang.lang) +#silent _ = t.gettext +#silent _t = t.gettext +#from kimchi.config import get_version +<!DOCTYPE html> +<html lang="$lang.lang[0]"> +<head> +<meta charset="UTF-8"> +<title>Kimchi</title> +<meta http-equiv="X-UA-Compatible" content="IE=edge"/> +<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" /> + +<style type="text/css"> +.login { + font-family: Arial; + margin: 0px; +} + +.login input.invalid-field { + border-color: #C85305 !important; +} + +.login .header { + background: none repeat scroll 0 0 #353D40; + border-bottom: 3px solid #008ABF; + border-top: 0 none; + box-shadow: 0 0 2px rgba(0, 0, 0, 0.5); + height: 50px; + color: #F8F8F8; + font-size: 13px; + font-weight: 700; + font-family: Helvetica; + overflow: hidden; +} + +.login .header .lang { + float: right; + margin-right: 20px; + margin-top: 14px; +} + +.login .header .lang select { + vertical-align: middle; +} + +.login .content-pane { + margin-left: auto; + margin-right: auto; + margin-top: 200px; + width: 260px; +} + +.login .content-pane .trademark { + margin-bottom: 30px; +} + +.login .content-pane .trademark .logo { + background: url("../images/logo.ico") no-repeat scroll center center transparent; + display: inline-block; + height: 25px; + width: 25px; + margin-left: -4px; + margin-right: 5px; + vertical-align: middle; +} + +.login .content-pane .trademark .name { + vertical-align: middle; + padding-top: 2px; + font-weight: bold; + font-size: 18px; +} + +.login .content-pane .trademark .version { + vertical-align: middle; + padding-top: 6px; + font-size: 13px; + padding-left: 6px; +} + +.login .content-pane .message-area .item { + font-size: 12px; + margin-bottom: 30px; + margin-top: 30px; + height: 20px; +} + +.login .content-pane .message-area .text { + color: #C85305; +} + +.login .progress-indicator .progress-icon { + margin-right: 3px; + vertical-align: middle; + width: 15px; + height: 15px; +} + +.login .progress-indicator .progress-text { + vertical-align: middle; + padding-top: 2px; +} + +.login .content-pane .hint { + margin-bottom: 10px; + font-size: 14px; +} + +.login .content-pane .field-area { + overflow: hidden; +} + +.login .content-pane .field-area .text-field { + width: 240px; + padding: 5px 7px; + margin-bottom: 5px; + border: 1px solid #BABABA; + border-radius: 1px; +} + +.login .button { + margin-top: 20px; + background: -moz-linear-gradient(center top , #1783BF 0%, #0C4C88 100%) repeat scroll 0 0 transparent; + border-color: #666666 #666666 #555555; + border-image: none; + border-radius: 5px 5px 5px 5px; + border-style: solid; + border-width: 1px; + color: #DDDDDD; + cursor: pointer; + font-weight: bolder; + padding: 5px 10px; + float: right; +} +</style> + +<script> + +function validateForm() { + var user = document.forms["login"]["username"]; + var pass = document.forms["login"]["password"]; + var validateField = function(field){ + field.className = "text-field"; + var isValid = field.value && field.value.trim()!="" ? true : false; + if(!isValid) field.className += " invalid-field"; + return isValid; + }; + var isValid = validateField(user); + isValid = validateField(pass) && isValid; + if(isValid) + document.getElementById("messWait").style.display = ""; + return isValid; +} + +function getCookie(cname) { + var name = cname + "="; + var ca = document.cookie.split(';'); + for(var i=0; i<ca.length; i++) { + var c = ca[i].trim(); + if (c.indexOf(name)==0) return c.substring(name.length,c.length); + } + return null; +} + +function setCookie(cname,cvalue,exdays) { + var d = new Date(); + d.setTime(d.getTime()+(exdays*24*60*60*1000)); + var expires = "expires="+d.toGMTString(); + document.cookie = cname + "=" + cvalue + "; " + expires; +} + +function init() { + var defaultLang = 'en_US'; + var clientLang = document.getElementById('userLang').value; + var persistLang = getCookie('kimchiLang'); + document.getElementById("userLang").value = persistLang || clientLang || defaultLang; +/* + var url = window.location.href; + if(url.indexOf("wrongUserPass")!=-1) + document.getElementById("messUserPass").style.display = ""; + if(url.indexOf("sessionTimeout")!=-1) + document.getElementById("messSession").style.display = ""; +*/ +} + +function changeLang() { + var lang = document.getElementById('userLang').value; + setCookie('kimchiLang', lang, 365); + window.location.reload(); +} + +</script> +</head> +<body class="login" onload="init()"> + +<div class="header"> + <div class="lang"> + <label>$_("Language"):</label> + <select id="userLang" onchange="changeLang()"> + <option value="en_US">English (US)</option> + <option value="zh_CN">??(??)</option> + <option value="pt_BR">Português (Brasil)</option> + </select> + </div> +</div> +<div class="content-pane"> + <div class="trademark"><span class="logo"></span><span class="name">Kimchi</span><span class="version">1.2</span></div> + <div class="message-area"> + <div id="messUserPass" class="item text" style="display: none;">$_("User Name or password is incorrect.")</div> + <div id="messSession" class="item text" style="display: none;">$_("Session timeout, please re-login.")</div> + <div id="messWait" class="item progress-indicator" style="display: none;"> + <img src="images/progressing.gif" class="progress-icon"><span class="progress-text">$_("Processing")...</span> + </div> + </div> + <div class="hint">$_("Sign in with your linux account")</div> + <div class="field-area"> + <form name="login" action="/login?next=$getVar('data.next', '/')" method="POST" onsubmit="return validateForm()"> + <input type="hidden" name="next" value="$getVar('data.next', '/')"> + <input type="text" name="username" placeholder="$_("User Name")" class="text-field" autofocus> + <input type="password" name="password" placeholder="$_("Password")" class="text-field"> + <input type="submit" value="$_("Sign In")" class="button"> + </form> + </div> +</div> + +</body> +</html>
_______________________________________________ Kimchi-devel mailing list Kimchi-devel@ovirt.org http://lists.ovirt.org/mailman/listinfo/kimchi-devel

On 06/03/2014 04:15 PM, Yu Xin Huo wrote:
On 6/3/2014 11:30 AM, Yu Xin Huo wrote:
tested, see issues below:
1. I always see the kimchi UI tabs before login page, as it is server side re-direct, why kimchi tabs appear?
2. when username or password is wrong, it is directed to an error page with content below, it should be back to login page with an error message.
/ERROR CODE/
// // /500 Internal Server Error/ //
/REASON/
// /The server encountered an unexpected condition which prevented it from fulfilling the request./ //
/STACK/
// // /Traceback (most recent call last): File "/usr/lib/python2.6/site-packages/cherrypy/_cprequest.py", line 656, in respond response.body = self.handler() File "/usr/lib/python2.6/site-packages/cherrypy/lib/encoding.py", line 188, in __call__ self.body = self.oldhandler(*args, **kwargs) File "/usr/lib/python2.6/site-packages/cherrypy/_cpdispatch.py", line 34, in __call__ return self.callable(*self.args, **self.kwargs) File "/root/kimchi-repo/test/kimchi/src/kimchi/root.py", line 129, in login auth.login(username, password) File "/root/kimchi-repo/test/kimchi/src/kimchi/auth.py", line 198, in login if not authenticate(username, password): File "/root/kimchi-repo/test/kimchi/src/kimchi/auth.py", line 135, in authenticate raise OperationFailed("KCHAUTH0001E", msg_args) OperationFailed: KCHAUTH0001E: Authentication failed for user 'root'. [Error code: 7]/ /3. there need to be message about "login fail" and "session timeout", need backend API available on html page to get the message./ seems it is hard to distinguish /session timeout //from longout. /
On 5/31/2014 1:16 AM, shaohef@linux.vnet.ibm.com wrote:
From: ShaoHe Feng<shaohef@linux.vnet.ibm.com>
this page is used for the session timeout or first login.
Signed-off-by: ShaoHe Feng<shaohef@linux.vnet.ibm.com> Signed-off-by: Yu Xin Huo<huoyuxin@linux.vnet.ibm.com> --- ui/images/progressing.gif | Bin 0 -> 1152 bytes ui/pages/login.html.tmpl | 247 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 247 insertions(+) create mode 100644 ui/images/progressing.gif create mode 100644 ui/pages/login.html.tmpl
diff --git a/ui/images/progressing.gif b/ui/images/progressing.gif new file mode 100644 index 0000000000000000000000000000000000000000..6552d41d9d4c874091bb51931c6adf64a95e8bd0 GIT binary patch literal 1152 zcmZ?wbhEHb6k!ly*v!E2|NsBHckiA#b7s?~O&uK_IXO9@p`oUxrgCy}4A_9;e{Mh5 zkYH!W09PYD17=2`8pWS1oFWVy3_2k7AY&O=+5}E^`WY^hIhD@I;2`qkhUamCHs#2? zD{Sl5ddqAu;o;E8n07H&VTOd$9w+z3Od8dz)1OOlg@hfQ?6P6gg)Nhut~h8s_iHy| zTx?f<DfNuF4qs+in1T70o7P)P87f1<g5(0~t-`bz%`;<c7;R*Hby&0+Cd*D$nyx)7 zxH>hoEs9-2GEYbl<TO?^r*$AZO&~F#<dR{_!xK!0-EtLPZ*p|yWoF`%>SmZA?aQ<9 zUT3kA$h=8X2{%vLaEeZ2FfFvxHCy+@)2xTXXx&nW19L8~I4mhFCLSR*N5YUN_g8RC zxvG$d3rC2Yoni>Hr8Z+mk+UtMt&Fyriq3S|nYyz*lh|s_)v7fmBnyPWjzbSOeSwpn ztM^*GK3gr@WX{W=;H4@s$Eix`o#&Z+UC|vq;?Mm$*qz>q{MpOLKD$V>lW^GM@gRp< zTfqAxmTMW#NQtz1Ow(GUENaLTnG@~OSSl%)a-~@^*=_L^Wu6LazRZG$dI^iu%U-z% zg<00g*_8=1ySk){v9Pk(*~<9qvQD2qQDdsojG1{NY_a__TQemj7eK-u-Fqm>f>utm zWMS=L&jJU059@Suul#8<RCK0juuU^pO9X~|9`=wYHdzoCYCehQmh?GGSt;IO&EY61 z^|cU^WKC}pQa3GC)^bS)J5HFrADAqr$@=Tg_KIeUMR6Q@nr+9QW_y9zNsLj!T)@YO zmFW>EN`0IXPrZ>S5M3ptD%hrTMQhc8T>+_g4tF#}E)IMpc<k8J3C>bEce!tTI4V-^ zEEL|{;B8wW%<SUK!k*>CYhksVX{CWv466RGb|aXRcN%49rjY*aHrnWY;d4a(eT< sn9_<U58lHODbH9KGQC;#6@s@G?AG7t-SQycLr1Fr#FC=U9tH+$0KoWQ9smFU
literal 0 HcmV?d00001
diff --git a/ui/pages/login.html.tmpl b/ui/pages/login.html.tmpl new file mode 100644 index 0000000..e7afbb3 --- /dev/null +++ b/ui/pages/login.html.tmpl @@ -0,0 +1,247 @@ +#* + * Project Kimchi + * + * Copyright IBM, Corp. 2014 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *# +#unicode UTF-8 +#import gettext +#from kimchi.cachebust import href +#silent t = gettext.translation($lang.domain, $lang.localedir, languages=$lang.lang) +#silent _ = t.gettext +#silent _t = t.gettext +#from kimchi.config import get_version +<!DOCTYPE html> +<html lang="$lang.lang[0]"> +<head> +<meta charset="UTF-8"> +<title>Kimchi</title> +<meta http-equiv="X-UA-Compatible" content="IE=edge"/> +<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" /> + +<style type="text/css"> +.login { + font-family: Arial; + margin: 0px; +} + +.login input.invalid-field { + border-color: #C85305 !important; +} + +.login .header { + background: none repeat scroll 0 0 #353D40; + border-bottom: 3px solid #008ABF; + border-top: 0 none; + box-shadow: 0 0 2px rgba(0, 0, 0, 0.5); + height: 50px; + color: #F8F8F8; + font-size: 13px; + font-weight: 700; + font-family: Helvetica; + overflow: hidden; +} + +.login .header .lang { + float: right; + margin-right: 20px; + margin-top: 14px; +} + +.login .header .lang select { + vertical-align: middle; +} + +.login .content-pane { + margin-left: auto; + margin-right: auto; + margin-top: 200px; + width: 260px; +} + +.login .content-pane .trademark { + margin-bottom: 30px; +} + +.login .content-pane .trademark .logo { + background: url("../images/logo.ico") no-repeat scroll center center transparent; + display: inline-block; + height: 25px; + width: 25px; + margin-left: -4px; + margin-right: 5px; + vertical-align: middle; +} + +.login .content-pane .trademark .name { + vertical-align: middle; + padding-top: 2px; + font-weight: bold; + font-size: 18px; +} + +.login .content-pane .trademark .version { + vertical-align: middle; + padding-top: 6px; + font-size: 13px; + padding-left: 6px; +} + +.login .content-pane .message-area .item { + font-size: 12px; + margin-bottom: 30px; + margin-top: 30px; + height: 20px; +} + +.login .content-pane .message-area .text { + color: #C85305; +} + +.login .progress-indicator .progress-icon { + margin-right: 3px; + vertical-align: middle; + width: 15px; + height: 15px; +} + +.login .progress-indicator .progress-text { + vertical-align: middle; + padding-top: 2px; +} + +.login .content-pane .hint { + margin-bottom: 10px; + font-size: 14px; +} + +.login .content-pane .field-area { + overflow: hidden; +} + +.login .content-pane .field-area .text-field { + width: 240px; + padding: 5px 7px; + margin-bottom: 5px; + border: 1px solid #BABABA; + border-radius: 1px; +} + +.login .button { + margin-top: 20px; + background: -moz-linear-gradient(center top , #1783BF 0%, #0C4C88 100%) repeat scroll 0 0 transparent; + border-color: #666666 #666666 #555555; + border-image: none; + border-radius: 5px 5px 5px 5px; + border-style: solid; + border-width: 1px; + color: #DDDDDD; + cursor: pointer; + font-weight: bolder; + padding: 5px 10px; + float: right; +} +</style> + +<script> + +function validateForm() { + var user = document.forms["login"]["username"]; + var pass = document.forms["login"]["password"]; + var validateField = function(field){ + field.className = "text-field"; + var isValid = field.value && field.value.trim()!="" ? true : false; + if(!isValid) field.className += " invalid-field"; + return isValid; + }; + var isValid = validateField(user); + isValid = validateField(pass) && isValid; + if(isValid) + document.getElementById("messWait").style.display = ""; + return isValid; +} + +function getCookie(cname) { + var name = cname + "="; + var ca = document.cookie.split(';'); + for(var i=0; i<ca.length; i++) { + var c = ca[i].trim(); + if (c.indexOf(name)==0) return c.substring(name.length,c.length); + } + return null; +} + +function setCookie(cname,cvalue,exdays) { + var d = new Date(); + d.setTime(d.getTime()+(exdays*24*60*60*1000)); + var expires = "expires="+d.toGMTString(); + document.cookie = cname + "=" + cvalue + "; " + expires; +} + +function init() { + var defaultLang = 'en_US'; + var clientLang = document.getElementById('userLang').value; + var persistLang = getCookie('kimchiLang'); + document.getElementById("userLang").value = persistLang || clientLang || defaultLang; +/* + var url = window.location.href; + if(url.indexOf("wrongUserPass")!=-1) + document.getElementById("messUserPass").style.display = ""; + if(url.indexOf("sessionTimeout")!=-1) + document.getElementById("messSession").style.display = ""; +*/ +} + +function changeLang() { + var lang = document.getElementById('userLang').value; + setCookie('kimchiLang', lang, 365); + window.location.reload(); +} + +</script> +</head> +<body class="login" onload="init()"> + +<div class="header"> + <div class="lang"> + <label>$_("Language"):</label> + <select id="userLang" onchange="changeLang()"> + <option value="en_US">English (US)</option> + <option value="zh_CN">??(??)</option> + <option value="pt_BR">Português (Brasil)</option> + </select> + </div> +</div> +<div class="content-pane"> + <div class="trademark"><span class="logo"></span><span class="name">Kimchi</span><span class="version">1.2</span></div> + <div class="message-area"> + <div id="messUserPass" class="item text" style="display: none;">$_("User Name or password is incorrect.")</div> + <div id="messSession" class="item text" style="display: none;">$_("Session timeout, please re-login.")</div> + <div id="messWait" class="item progress-indicator" style="display: none;"> + <img src="images/progressing.gif" class="progress-icon"><span class="progress-text">$_("Processing")...</span> + </div> + </div> + <div class="hint">$_("Sign in with your linux account")</div> + <div class="field-area"> + <form name="login" action="/login?next=$getVar('data.next', '/')" method="POST" onsubmit="return validateForm()"> + <input type="hidden" name="next" value="$getVar('data.next', '/')"> + <input type="text" name="username" placeholder="$_("User Name")" class="text-field" autofocus> + <input type="password" name="password" placeholder="$_("Password")" class="text-field"> + <input type="submit" value="$_("Sign In")" class="button"> + </form> + </div> +</div> + +</body> +</html>
_______________________________________________ Kimchi-devel mailing list Kimchi-devel@ovirt.org http://lists.ovirt.org/mailman/listinfo/kimchi-devel
_______________________________________________ Kimchi-devel mailing list Kimchi-devel@ovirt.org http://lists.ovirt.org/mailman/listinfo/kimchi-devel
-- Thanks and best regards! Sheldon Feng(???)<shaohef@linux.vnet.ibm.com> IBM Linux Technology Center
participants (3)
-
shaohef@linux.vnet.ibm.com
-
Sheldon
-
Yu Xin Huo