Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Tan Jiang 2016-04-05 20:46:46 +08:00
commit 88303cf2a2
12 changed files with 142 additions and 36 deletions

View File

@ -30,4 +30,6 @@ ldap_basedn = uid=%s,ou=people,dc=mydomain,dc=com
#The password for the root user of mysql db, change this before any production use. #The password for the root user of mysql db, change this before any production use.
db_password = root123 db_password = root123
#Switch for self-registration feature
self_registration = on
##### #####

View File

@ -25,6 +25,7 @@ auth_mode = cp.get("configuration", "auth_mode")
ldap_url = cp.get("configuration", "ldap_url") ldap_url = cp.get("configuration", "ldap_url")
ldap_basedn = cp.get("configuration", "ldap_basedn") ldap_basedn = cp.get("configuration", "ldap_basedn")
db_password = cp.get("configuration", "db_password") db_password = cp.get("configuration", "db_password")
self_registration = cp.get("configuration", "self_registration")
######## ########
base_dir = os.path.dirname(__file__) base_dir = os.path.dirname(__file__)
@ -65,7 +66,8 @@ render(os.path.join(templates_dir, "ui", "env"),
auth_mode=auth_mode, auth_mode=auth_mode,
admin_pwd=harbor_admin_password, admin_pwd=harbor_admin_password,
ldap_url=ldap_url, ldap_url=ldap_url,
ldap_basedn=ldap_basedn) ldap_basedn=ldap_basedn,
self_registration=self_registration)
render(os.path.join(templates_dir, "ui", "app.conf"), render(os.path.join(templates_dir, "ui", "app.conf"),
ui_conf, ui_conf,

View File

@ -10,4 +10,5 @@ HARBOR_URL=$ui_url
AUTH_MODE=$auth_mode AUTH_MODE=$auth_mode
LDAP_URL=$ldap_url LDAP_URL=$ldap_url
LDAP_BASE_DN=$ldap_basedn LDAP_BASE_DN=$ldap_basedn
SELF_REGISTRATION=$self_registration
LOG_LEVEL=debug LOG_LEVEL=debug

View File

@ -16,12 +16,14 @@
package controllers package controllers
import ( import (
"net/http"
"os" "os"
"strings" "strings"
"github.com/vmware/harbor/utils/log"
"github.com/astaxie/beego" "github.com/astaxie/beego"
"github.com/beego/i18n" "github.com/beego/i18n"
"github.com/vmware/harbor/dao"
"github.com/vmware/harbor/utils/log"
) )
// CommonController handles request from UI that doesn't expect a page, such as /login /logout ... // CommonController handles request from UI that doesn't expect a page, such as /login /logout ...
@ -38,6 +40,9 @@ func (c *CommonController) Render() error {
type BaseController struct { type BaseController struct {
beego.Controller beego.Controller
i18n.Locale i18n.Locale
SelfRegistration bool
IsAdmin bool
AuthMode string
} }
type langType struct { type langType struct {
@ -93,15 +98,35 @@ func (b *BaseController) Prepare() {
b.Data["CurLang"] = curLang.Name b.Data["CurLang"] = curLang.Name
b.Data["RestLangs"] = restLangs b.Data["RestLangs"] = restLangs
sessionUserID := b.GetSession("userId") authMode := strings.ToLower(os.Getenv("AUTH_MODE"))
if sessionUserID != nil {
b.Data["Username"] = b.GetSession("username")
}
authMode := os.Getenv("AUTH_MODE")
if authMode == "" { if authMode == "" {
authMode = "db_auth" authMode = "db_auth"
} }
b.Data["AuthMode"] = authMode b.AuthMode = authMode
b.Data["AuthMode"] = b.AuthMode
selfRegistration := strings.ToLower(os.Getenv("SELF_REGISTRATION"))
if selfRegistration == "on" {
b.SelfRegistration = true
}
sessionUserID := b.GetSession("userId")
if sessionUserID != nil {
b.Data["Username"] = b.GetSession("username")
b.Data["UserId"] = sessionUserID.(int)
var err error
b.IsAdmin, err = dao.IsAdminRole(sessionUserID.(int))
if err != nil {
log.Errorf("Error occurred in IsAdminRole:%v", err)
b.CustomAbort(http.StatusInternalServerError, "Internal error.")
}
}
b.Data["IsAdmin"] = b.IsAdmin
b.Data["SelfRegistration"] = b.SelfRegistration
} }
// ForwardTo setup layout and template for content for a page. // ForwardTo setup layout and template for content for a page.

View File

@ -17,11 +17,11 @@ package controllers
import ( import (
"net/http" "net/http"
"os"
"strings" "strings"
"github.com/vmware/harbor/dao" "github.com/vmware/harbor/dao"
"github.com/vmware/harbor/models" "github.com/vmware/harbor/models"
"github.com/vmware/harbor/utils/log" "github.com/vmware/harbor/utils/log"
) )
@ -32,35 +32,70 @@ type RegisterController struct {
// Get renders the Sign In page, it only works if the auth mode is set to db_auth // Get renders the Sign In page, it only works if the auth mode is set to db_auth
func (rc *RegisterController) Get() { func (rc *RegisterController) Get() {
authMode := os.Getenv("AUTH_MODE")
if authMode == "" || authMode == "db_auth" { if !rc.SelfRegistration {
log.Warning("Registration is disabled when self-registration is off.")
rc.Redirect("/signIn", http.StatusFound)
}
if rc.AuthMode == "db_auth" {
rc.ForwardTo("page_title_registration", "register") rc.ForwardTo("page_title_registration", "register")
} else { } else {
rc.Redirect("/signIn", http.StatusNotFound) rc.Redirect("/signIn", http.StatusFound)
}
}
// AddUserController handles request for adding user with an admin role user
type AddUserController struct {
BaseController
}
// Get renders the Sign In page, it only works if the auth mode is set to db_auth
func (ac *AddUserController) Get() {
if !ac.IsAdmin {
log.Warning("Add user can only be used by admin role user.")
ac.Redirect("/signIn", http.StatusFound)
}
if ac.AuthMode == "db_auth" {
ac.ForwardTo("page_title_add_user", "register")
} else {
ac.Redirect("/signIn", http.StatusFound)
} }
} }
// SignUp insert data into DB based on data in form. // SignUp insert data into DB based on data in form.
func (rc *CommonController) SignUp() { func (cc *CommonController) SignUp() {
username := strings.TrimSpace(rc.GetString("username"))
email := strings.TrimSpace(rc.GetString("email")) if !(cc.AuthMode == "db_auth") {
realname := strings.TrimSpace(rc.GetString("realname")) cc.CustomAbort(http.StatusForbidden, "")
password := strings.TrimSpace(rc.GetString("password")) }
comment := strings.TrimSpace(rc.GetString("comment"))
if !(cc.SelfRegistration || cc.IsAdmin) {
log.Warning("Registration can only be used by admin role user when self-registration is off.")
cc.CustomAbort(http.StatusForbidden, "")
}
username := strings.TrimSpace(cc.GetString("username"))
email := strings.TrimSpace(cc.GetString("email"))
realname := strings.TrimSpace(cc.GetString("realname"))
password := strings.TrimSpace(cc.GetString("password"))
comment := strings.TrimSpace(cc.GetString("comment"))
user := models.User{Username: username, Email: email, Realname: realname, Password: password, Comment: comment} user := models.User{Username: username, Email: email, Realname: realname, Password: password, Comment: comment}
_, err := dao.Register(user) _, err := dao.Register(user)
if err != nil { if err != nil {
log.Errorf("Error occurred in Register: %v", err) log.Errorf("Error occurred in Register: %v", err)
rc.CustomAbort(http.StatusInternalServerError, "Internal error.") cc.CustomAbort(http.StatusInternalServerError, "Internal error.")
} }
} }
// UserExists checks if user exists when user input value in sign in form. // UserExists checks if user exists when user input value in sign in form.
func (rc *CommonController) UserExists() { func (cc *CommonController) UserExists() {
target := rc.GetString("target") target := cc.GetString("target")
value := rc.GetString("value") value := cc.GetString("value")
user := models.User{} user := models.User{}
switch target { switch target {
@ -73,8 +108,8 @@ func (rc *CommonController) UserExists() {
exist, err := dao.UserExists(user, target) exist, err := dao.UserExists(user, target)
if err != nil { if err != nil {
log.Errorf("Error occurred in UserExists: %v", err) log.Errorf("Error occurred in UserExists: %v", err)
rc.CustomAbort(http.StatusInternalServerError, "Internal error.") cc.CustomAbort(http.StatusInternalServerError, "Internal error.")
} }
rc.Data["json"] = exist cc.Data["json"] = exist
rc.ServeJSON() cc.ServeJSON()
} }

View File

@ -41,6 +41,7 @@ func init() {
beego.Router("/", &controllers.IndexController{}) beego.Router("/", &controllers.IndexController{})
beego.Router("/signIn", &controllers.SignInController{}) beego.Router("/signIn", &controllers.SignInController{})
beego.Router("/register", &controllers.RegisterController{}) beego.Router("/register", &controllers.RegisterController{})
beego.Router("/addUser", &controllers.AddUserController{})
beego.Router("/forgotPassword", &controllers.ForgotPasswordController{}) beego.Router("/forgotPassword", &controllers.ForgotPasswordController{})
beego.Router("/resetPassword", &controllers.ResetPasswordController{}) beego.Router("/resetPassword", &controllers.ResetPasswordController{})
beego.Router("/changePassword", &controllers.ChangePasswordController{}) beego.Router("/changePassword", &controllers.ChangePasswordController{})

View File

@ -3,6 +3,7 @@ page_title_sign_in = Sign In - Harbor
page_title_project = Project - Harbor page_title_project = Project - Harbor
page_title_item_details = Details - Harbor page_title_item_details = Details - Harbor
page_title_registration = Sign Up - Harbor page_title_registration = Sign Up - Harbor
page_title_add_user = Add User - Harbor
page_title_forgot_password = Forgot Password - Harbor page_title_forgot_password = Forgot Password - Harbor
title_forgot_password = Forgot Password title_forgot_password = Forgot Password
page_title_reset_password = Reset Password - Harbor page_title_reset_password = Reset Password - Harbor
@ -12,6 +13,7 @@ title_change_password = Change Password
page_title_search = Search - Harbor page_title_search = Search - Harbor
sign_in = Sign In sign_in = Sign In
sign_up = Sign Up sign_up = Sign Up
add_user = Add User
log_out = Log Out log_out = Log Out
search_placeholder = projects or repositories search_placeholder = projects or repositories
change_password = Change Password change_password = Change Password

View File

@ -177,6 +177,10 @@ var global_messages = {
"en-US": "Sign Up", "en-US": "Sign Up",
"zh-CN": "注册" "zh-CN": "注册"
}, },
"title_add_user": {
"en-US": "Add User",
"zh-CN": "新增用户"
},
"registered_successfully": { "registered_successfully": {
"en-US": "Signed up successfully.", "en-US": "Signed up successfully.",
"zh-CN": "注册成功。" "zh-CN": "注册成功。"
@ -185,6 +189,14 @@ var global_messages = {
"en-US": "Failed to sign up.", "en-US": "Failed to sign up.",
"zh-CN": "注册失败。" "zh-CN": "注册失败。"
}, },
"added_user_successfully": {
"en-US": "Added user successfully.",
"zh-CN": "新增用户成功。"
},
"added_user_failed": {
"en-US": "Added user failed.",
"zh-CN": "新增用户失败。"
},
"projects" : { "projects" : {
"en-US": "Projects", "en-US": "Projects",
"zh-CN": "项目" "zh-CN": "项目"

View File

@ -3,6 +3,7 @@ page_title_sign_in = 登录 - Harbor
page_title_project = 项目 - Harbor page_title_project = 项目 - Harbor
page_title_item_details = 详细信息 - Harbor page_title_item_details = 详细信息 - Harbor
page_title_registration = 注册 - Harbor page_title_registration = 注册 - Harbor
page_title_add_user = 新增用户 - Harbor
page_title_forgot_password = 忘记密码 - Harbor page_title_forgot_password = 忘记密码 - Harbor
title_forgot_password = 忘记密码 title_forgot_password = 忘记密码
page_title_reset_password = 重置密码 - Harbor page_title_reset_password = 重置密码 - Harbor
@ -12,6 +13,7 @@ title_change_password = 修改密码
page_title_search = 搜索 - Harbor page_title_search = 搜索 - Harbor
sign_in = 登录 sign_in = 登录
sign_up = 注册 sign_up = 注册
add_user = 新增用户
log_out = 注销 log_out = 注销
search_placeholder = 项目或镜像名称 search_placeholder = 项目或镜像名称
change_password = 修改密码 change_password = 修改密码

View File

@ -30,12 +30,14 @@ jQuery(function(){
$("#btnPageSignUp").on("click", function(){ $("#btnPageSignUp").on("click", function(){
validateOptions.Validate(function() { validateOptions.Validate(function() {
var username = $.trim($("#Username").val()); var username = $.trim($("#Username").val());
var email = $.trim($("#Email").val()); var email = $.trim($("#Email").val());
var password = $.trim($("#Password").val()); var password = $.trim($("#Password").val());
var confirmedPassword = $.trim($("#ConfirmedPassword").val()); var confirmedPassword = $.trim($("#ConfirmedPassword").val());
var realname = $.trim($("#Realname").val()); var realname = $.trim($("#Realname").val());
var comment = $.trim($("#Comment").val()); var comment = $.trim($("#Comment").val());
var isAdmin = $("#isAdmin").val();
$.ajax({ $.ajax({
url : '/signUp', url : '/signUp',
data:{username: username, password: password, realname: realname, comment: comment, email: email}, data:{username: username, password: password, realname: realname, comment: comment, email: email},
@ -47,10 +49,14 @@ jQuery(function(){
if(xhr && xhr.status == 200){ if(xhr && xhr.status == 200){
$("#dlgModal") $("#dlgModal")
.dialogModal({ .dialogModal({
"title": i18n.getMessage("title_sign_up"), "title": isAdmin == "true" ? i18n.getMessage("title_add_user") : i18n.getMessage("title_sign_up"),
"content": i18n.getMessage("registered_successfully"), "content": isAdmin == "true" ? i18n.getMessage("added_user_successfully") : i18n.getMessage("registered_successfully"),
"callback": function(){ "callback": function(){
document.location = "/signIn"; if(isAdmin == "true") {
document.location = "/registry/project";
}else{
document.location = "/signIn";
}
} }
}); });
} }

View File

@ -16,7 +16,11 @@
<div class="col-sm-4"></div> <div class="col-sm-4"></div>
<div class="col-sm-4"> <div class="col-sm-4">
<div class="page-header"> <div class="page-header">
{{ if eq .IsAdmin true }}
<h1>{{i18n .Lang "add_user" }}</h1>
{{ else }}
<h1>{{i18n .Lang "registration"}}</h1> <h1>{{i18n .Lang "registration"}}</h1>
{{ end }}
</div> </div>
<form class="form"> <form class="form">
<div class="alert alert-danger" role="alert" id="divErrMsg"></div> <div class="alert alert-danger" role="alert" id="divErrMsg"></div>
@ -62,7 +66,13 @@
</div> </div>
<div class="form-group has-feedback"> <div class="form-group has-feedback">
<div class="text-center"> <div class="text-center">
<button type="button" class="btn btn-default" id="btnPageSignUp">{{i18n .Lang "sign_up"}}</button> <button type="button" class="btn btn-default" id="btnPageSignUp">
{{ if eq .IsAdmin true }}
{{i18n .Lang "add_user" }}
{{ else }}
{{i18n .Lang "sign_up"}}
{{ end }}
</button>
</div> </div>
</div> </div>
</form> </form>

View File

@ -13,6 +13,7 @@
limitations under the License. limitations under the License.
--> -->
<input type="hidden" id="currentLanguage" value="{{.Lang}}"> <input type="hidden" id="currentLanguage" value="{{.Lang}}">
<input type="hidden" id="isAdmin" value="{{.IsAdmin}}">
<nav class="navbar navbar-default" role="navigation" style="margin-bottom: 0;"> <nav class="navbar navbar-default" role="navigation" style="margin-bottom: 0;">
<div class="navbar-header"> <div class="navbar-header">
<button aria-controls="navbar" aria-expanded="false" data-target="#navbar" data-toggle="collapse" class="navbar-toggle collapsed" type="button"> <button aria-controls="navbar" aria-expanded="false" data-target="#navbar" data-toggle="collapse" class="navbar-toggle collapsed" type="button">
@ -55,6 +56,11 @@
<li><a id="aChangePassword" href="/changePassword" target="_blank"><span class="glyphicon glyphicon-pencil"></span>&nbsp;&nbsp;{{i18n .Lang "change_password"}}</a></li> <li><a id="aChangePassword" href="/changePassword" target="_blank"><span class="glyphicon glyphicon-pencil"></span>&nbsp;&nbsp;{{i18n .Lang "change_password"}}</a></li>
<li role="separator" class="divider"></li> <li role="separator" class="divider"></li>
{{ end }} {{ end }}
{{ if eq .AuthMode "db_auth" }}
{{ if eq .IsAdmin true }}
<li><a id="aAddUser" href="/addUser" target="_blank"><span class="glyphicon glyphicon-plus"></span>&nbsp;&nbsp;{{i18n .Lang "add_user"}}</a></li>
{{ end }}
{{ end}}
<li><a id="aLogout" href="#"><span class="glyphicon glyphicon-log-in"></span>&nbsp;&nbsp;{{i18n .Lang "log_out"}}</a></li> <li><a id="aLogout" href="#"><span class="glyphicon glyphicon-log-in"></span>&nbsp;&nbsp;{{i18n .Lang "log_out"}}</a></li>
</ul> </ul>
</li> </li>
@ -63,7 +69,9 @@
{{ else if eq .AuthMode "db_auth" }} {{ else if eq .AuthMode "db_auth" }}
<div class="input-group"> <div class="input-group">
&nbsp;<button type="button" class="btn btn-default" id="btnSignIn">{{i18n .Lang "sign_in"}}</button> &nbsp;<button type="button" class="btn btn-default" id="btnSignIn">{{i18n .Lang "sign_in"}}</button>
{{ if eq .SelfRegistration true }}
&nbsp;<button type="button" class="btn btn-success" id="btnSignUp">{{i18n .Lang "sign_up"}}</button> &nbsp;<button type="button" class="btn btn-success" id="btnSignUp">{{i18n .Lang "sign_up"}}</button>
{{ end }}
</div> </div>
{{ else }} {{ else }}
<div class="input-group"> <div class="input-group">