mirror of
https://github.com/goharbor/harbor.git
synced 2024-11-27 12:46:03 +01:00
Merge branch 'master' into bugx_fix
This commit is contained in:
commit
e240290bc7
@ -1511,6 +1511,18 @@ paths:
|
|||||||
format: int64
|
format: int64
|
||||||
required: false
|
required: false
|
||||||
description: Relevant project ID.
|
description: Relevant project ID.
|
||||||
|
- name: page
|
||||||
|
in: query
|
||||||
|
type: integer
|
||||||
|
format: int32
|
||||||
|
required: false
|
||||||
|
description: 'The page nubmer.'
|
||||||
|
- name: page_size
|
||||||
|
in: query
|
||||||
|
type: integer
|
||||||
|
format: int32
|
||||||
|
required: false
|
||||||
|
description: 'The size of per page.'
|
||||||
tags:
|
tags:
|
||||||
- Products
|
- Products
|
||||||
responses:
|
responses:
|
||||||
|
@ -365,7 +365,13 @@ func GetDatabaseFromCfg(cfg map[string]interface{}) *models.Database {
|
|||||||
|
|
||||||
// Valid LDAP Scope
|
// Valid LDAP Scope
|
||||||
func validLdapScope(cfg map[string]interface{}, isMigrate bool) {
|
func validLdapScope(cfg map[string]interface{}, isMigrate bool) {
|
||||||
ldapScope := cfg[ldapScopeKey].(int)
|
ldapScope, ok := cfg[ldapScopeKey].(int)
|
||||||
|
if !ok {
|
||||||
|
ldapScopeFloat, ok := cfg[ldapScopeKey].(float64)
|
||||||
|
if ok {
|
||||||
|
ldapScope = int(ldapScopeFloat)
|
||||||
|
}
|
||||||
|
}
|
||||||
if isMigrate && ldapScope > 0 && ldapScope < 3 {
|
if isMigrate && ldapScope > 0 && ldapScope < 3 {
|
||||||
ldapScope = ldapScope - 1
|
ldapScope = ldapScope - 1
|
||||||
}
|
}
|
||||||
|
@ -143,6 +143,8 @@ func TestGetDatabaseFromCfg(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestValidLdapScope(t *testing.T) {
|
func TestValidLdapScope(t *testing.T) {
|
||||||
|
var dbValue float64
|
||||||
|
dbValue = 2
|
||||||
ldapScopeKey := "ldap_scope"
|
ldapScopeKey := "ldap_scope"
|
||||||
testCfgs := []struct {
|
testCfgs := []struct {
|
||||||
config map[string]interface{}
|
config map[string]interface{}
|
||||||
@ -167,6 +169,9 @@ func TestValidLdapScope(t *testing.T) {
|
|||||||
{map[string]interface{}{
|
{map[string]interface{}{
|
||||||
ldapScopeKey: -100,
|
ldapScopeKey: -100,
|
||||||
}, false, 0},
|
}, false, 0},
|
||||||
|
{map[string]interface{}{
|
||||||
|
ldapScopeKey: dbValue,
|
||||||
|
}, false, 2},
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, item := range testCfgs {
|
for i, item := range testCfgs {
|
||||||
|
@ -21,6 +21,7 @@ import (
|
|||||||
|
|
||||||
"github.com/astaxie/beego/orm"
|
"github.com/astaxie/beego/orm"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
"github.com/vmware/harbor/src/common"
|
"github.com/vmware/harbor/src/common"
|
||||||
"github.com/vmware/harbor/src/common/models"
|
"github.com/vmware/harbor/src/common/models"
|
||||||
"github.com/vmware/harbor/src/common/utils"
|
"github.com/vmware/harbor/src/common/utils"
|
||||||
@ -1253,8 +1254,13 @@ func TestDeleteRepTarget(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetTotalOfRepPolicies(t *testing.T) {
|
||||||
|
_, err := GetTotalOfRepPolicies("", 1)
|
||||||
|
require.Nil(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
func TestFilterRepPolicies(t *testing.T) {
|
func TestFilterRepPolicies(t *testing.T) {
|
||||||
_, err := FilterRepPolicies("name", 0)
|
_, err := FilterRepPolicies("name", 0, 0, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to filter policy: %v", err)
|
t.Fatalf("failed to filter policy: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -139,8 +139,23 @@ func GetRepPolicy(id int64) (*models.RepPolicy, error) {
|
|||||||
return &policy, nil
|
return &policy, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetTotalOfRepPolicies returns the total count of replication policies
|
||||||
|
func GetTotalOfRepPolicies(name string, projectID int64) (int64, error) {
|
||||||
|
qs := GetOrmer().QueryTable(&models.RepPolicy{}).Filter("deleted", 0)
|
||||||
|
|
||||||
|
if len(name) != 0 {
|
||||||
|
qs = qs.Filter("name__icontains", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
if projectID != 0 {
|
||||||
|
qs = qs.Filter("project_id", projectID)
|
||||||
|
}
|
||||||
|
|
||||||
|
return qs.Count()
|
||||||
|
}
|
||||||
|
|
||||||
// FilterRepPolicies filters policies by name and project ID
|
// FilterRepPolicies filters policies by name and project ID
|
||||||
func FilterRepPolicies(name string, projectID int64) ([]*models.RepPolicy, error) {
|
func FilterRepPolicies(name string, projectID, page, pageSize int64) ([]*models.RepPolicy, error) {
|
||||||
o := GetOrmer()
|
o := GetOrmer()
|
||||||
|
|
||||||
var args []interface{}
|
var args []interface{}
|
||||||
@ -170,6 +185,11 @@ func FilterRepPolicies(name string, projectID int64) ([]*models.RepPolicy, error
|
|||||||
|
|
||||||
sql += `group by rp.id order by rp.creation_time`
|
sql += `group by rp.id order by rp.creation_time`
|
||||||
|
|
||||||
|
if page > 0 && pageSize > 0 {
|
||||||
|
sql += ` limit ? offset ?`
|
||||||
|
args = append(args, pageSize, (page-1)*pageSize)
|
||||||
|
}
|
||||||
|
|
||||||
var policies []*models.RepPolicy
|
var policies []*models.RepPolicy
|
||||||
if _, err := o.Raw(sql, args).QueryRows(&policies); err != nil {
|
if _, err := o.Raw(sql, args).QueryRows(&policies); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -22,8 +22,8 @@ import (
|
|||||||
type FakePolicyManager struct {
|
type FakePolicyManager struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FakePolicyManager) GetPolicies(query models.QueryParameter) ([]models.ReplicationPolicy, error) {
|
func (f *FakePolicyManager) GetPolicies(query models.QueryParameter) (*models.ReplicationPolicyQueryResult, error) {
|
||||||
return []models.ReplicationPolicy{}, nil
|
return &models.ReplicationPolicyQueryResult{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FakePolicyManager) GetPolicy(id int64) (models.ReplicationPolicy, error) {
|
func (f *FakePolicyManager) GetPolicy(id int64) (models.ReplicationPolicy, error) {
|
||||||
|
@ -98,18 +98,17 @@ func (ctl *DefaultController) Init() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//Build query parameters
|
policies, err := ctl.policyManager.GetPolicies(models.QueryParameter{})
|
||||||
query := models.QueryParameter{
|
|
||||||
TriggerType: replication.TriggerKindSchedule,
|
|
||||||
}
|
|
||||||
|
|
||||||
policies, err := ctl.policyManager.GetPolicies(query)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if policies != nil && len(policies) > 0 {
|
if policies != nil && len(policies.Policies) > 0 {
|
||||||
for _, policy := range policies {
|
for _, policy := range policies.Policies {
|
||||||
if err := ctl.triggerManager.SetupTrigger(&policy); err != nil {
|
if policy.Trigger == nil || policy.Trigger.Kind != replication.TriggerKindSchedule {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctl.triggerManager.SetupTrigger(policy); err != nil {
|
||||||
log.Errorf("failed to setup trigger for policy %v: %v", policy, err)
|
log.Errorf("failed to setup trigger for policy %v: %v", policy, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -209,7 +208,7 @@ func (ctl *DefaultController) GetPolicy(policyID int64) (models.ReplicationPolic
|
|||||||
}
|
}
|
||||||
|
|
||||||
//GetPolicies is delegation of GetPoliciemodels.ReplicationPolicy{}s of Policy.Manager
|
//GetPolicies is delegation of GetPoliciemodels.ReplicationPolicy{}s of Policy.Manager
|
||||||
func (ctl *DefaultController) GetPolicies(query models.QueryParameter) ([]models.ReplicationPolicy, error) {
|
func (ctl *DefaultController) GetPolicies(query models.QueryParameter) (*models.ReplicationPolicyQueryResult, error) {
|
||||||
return ctl.policyManager.GetPolicies(query)
|
return ctl.policyManager.GetPolicies(query)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,12 +27,15 @@ type QueryParameter struct {
|
|||||||
//Size of each page, couple with page
|
//Size of each page, couple with page
|
||||||
PageSize int64
|
PageSize int64
|
||||||
|
|
||||||
//Query by the type of trigger
|
|
||||||
TriggerType string
|
|
||||||
|
|
||||||
//Query by project ID
|
//Query by project ID
|
||||||
ProjectID int64
|
ProjectID int64
|
||||||
|
|
||||||
//Query by name
|
//Query by name
|
||||||
Name string
|
Name string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReplicationPolicyQueryResult is the query result of replication policy
|
||||||
|
type ReplicationPolicyQueryResult struct {
|
||||||
|
Total int64
|
||||||
|
Policies []*ReplicationPolicy
|
||||||
|
}
|
||||||
|
@ -26,7 +26,7 @@ import (
|
|||||||
|
|
||||||
// Manager defines the method a policy manger should implement
|
// Manager defines the method a policy manger should implement
|
||||||
type Manager interface {
|
type Manager interface {
|
||||||
GetPolicies(models.QueryParameter) ([]models.ReplicationPolicy, error)
|
GetPolicies(models.QueryParameter) (*models.ReplicationPolicyQueryResult, error)
|
||||||
GetPolicy(int64) (models.ReplicationPolicy, error)
|
GetPolicy(int64) (models.ReplicationPolicy, error)
|
||||||
CreatePolicy(models.ReplicationPolicy) (int64, error)
|
CreatePolicy(models.ReplicationPolicy) (int64, error)
|
||||||
UpdatePolicy(models.ReplicationPolicy) error
|
UpdatePolicy(models.ReplicationPolicy) error
|
||||||
@ -42,27 +42,28 @@ func NewDefaultManager() *DefaultManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//GetPolicies returns all the policies
|
//GetPolicies returns all the policies
|
||||||
func (m *DefaultManager) GetPolicies(query models.QueryParameter) ([]models.ReplicationPolicy, error) {
|
func (m *DefaultManager) GetPolicies(query models.QueryParameter) (*models.ReplicationPolicyQueryResult, error) {
|
||||||
result := []models.ReplicationPolicy{}
|
result := &models.ReplicationPolicyQueryResult{
|
||||||
//TODO support more query conditions other than name and project ID
|
Policies: []*models.ReplicationPolicy{},
|
||||||
policies, err := dao.FilterRepPolicies(query.Name, query.ProjectID)
|
}
|
||||||
|
total, err := dao.GetTotalOfRepPolicies(query.Name, query.ProjectID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return result, err
|
return nil, err
|
||||||
|
}
|
||||||
|
result.Total = total
|
||||||
|
|
||||||
|
policies, err := dao.FilterRepPolicies(query.Name, query.ProjectID, query.Page, query.PageSize)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, policy := range policies {
|
for _, policy := range policies {
|
||||||
ply, err := convertFromPersistModel(policy)
|
ply, err := convertFromPersistModel(policy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []models.ReplicationPolicy{}, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(query.TriggerType) > 0 {
|
result.Policies = append(result.Policies, &ply)
|
||||||
if ply.Trigger.Kind != query.TriggerType {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
result = append(result, ply)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result, nil
|
return result, nil
|
||||||
|
@ -82,7 +82,7 @@ func (ra *RepJobAPI) List() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
repository := ra.GetString("repository")
|
repository := ra.GetString("repository")
|
||||||
status := ra.GetString("status")
|
statuses := ra.GetStrings("status")
|
||||||
|
|
||||||
var startTime *time.Time
|
var startTime *time.Time
|
||||||
startTimeStr := ra.GetString("start_time")
|
startTimeStr := ra.GetString("start_time")
|
||||||
@ -108,15 +108,11 @@ func (ra *RepJobAPI) List() {
|
|||||||
|
|
||||||
page, pageSize := ra.GetPaginationParams()
|
page, pageSize := ra.GetPaginationParams()
|
||||||
|
|
||||||
statuses := []string{}
|
|
||||||
if len(status) > 0 {
|
|
||||||
statuses = append(statuses, status)
|
|
||||||
}
|
|
||||||
jobs, total, err := dao.FilterRepJobs(policyID, repository, statuses,
|
jobs, total, err := dao.FilterRepJobs(policyID, repository, statuses,
|
||||||
startTime, endTime, pageSize, pageSize*(page-1))
|
startTime, endTime, pageSize, pageSize*(page-1))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("failed to filter jobs according policy ID %d, repository %s, status %s, start time %v, end time %v: %v",
|
log.Errorf("failed to filter jobs according policy ID %d, repository %s, status %v, start time %v, end time %v: %v",
|
||||||
policyID, repository, status, startTime, endTime, err)
|
policyID, repository, statuses, startTime, endTime, err)
|
||||||
ra.CustomAbort(http.StatusInternalServerError, "")
|
ra.CustomAbort(http.StatusInternalServerError, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,28 +89,34 @@ func (pa *RepPolicyAPI) List() {
|
|||||||
}
|
}
|
||||||
queryParam.ProjectID = projectID
|
queryParam.ProjectID = projectID
|
||||||
}
|
}
|
||||||
|
queryParam.Page, queryParam.PageSize = pa.GetPaginationParams()
|
||||||
|
|
||||||
result := []*api_models.ReplicationPolicy{}
|
result, err := core.GlobalController.GetPolicies(queryParam)
|
||||||
|
|
||||||
policies, err := core.GlobalController.GetPolicies(queryParam)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("failed to get policies: %v, query parameters: %v", err, queryParam)
|
log.Errorf("failed to get policies: %v, query parameters: %v", err, queryParam)
|
||||||
pa.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError))
|
pa.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError))
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, policy := range policies {
|
var total int64
|
||||||
if !pa.SecurityCtx.HasAllPerm(policy.ProjectIDs[0]) {
|
policies := []*api_models.ReplicationPolicy{}
|
||||||
continue
|
if result != nil {
|
||||||
|
total = result.Total
|
||||||
|
for _, policy := range result.Policies {
|
||||||
|
if !pa.SecurityCtx.HasAllPerm(policy.ProjectIDs[0]) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ply, err := convertFromRepPolicy(pa.ProjectMgr, *policy)
|
||||||
|
if err != nil {
|
||||||
|
pa.ParseAndHandleError(fmt.Sprintf("failed to convert from replication policy"), err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
policies = append(policies, ply)
|
||||||
}
|
}
|
||||||
ply, err := convertFromRepPolicy(pa.ProjectMgr, policy)
|
|
||||||
if err != nil {
|
|
||||||
pa.ParseAndHandleError(fmt.Sprintf("failed to convert from replication policy"), err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
result = append(result, ply)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pa.Data["json"] = result
|
pa.SetPaginationHeader(total, queryParam.Page, queryParam.PageSize)
|
||||||
|
|
||||||
|
pa.Data["json"] = policies
|
||||||
pa.ServeJSON()
|
pa.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "harbor-ui",
|
"name": "harbor-ui",
|
||||||
"version": "0.6.22",
|
"version": "0.6.25",
|
||||||
"description": "Harbor shared UI components based on Clarity and Angular4",
|
"description": "Harbor shared UI components based on Clarity and Angular4",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "ng serve --host 0.0.0.0 --port 4500 --proxy-config proxy.config.json",
|
"start": "ng serve --host 0.0.0.0 --port 4500 --proxy-config proxy.config.json",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "harbor-ui",
|
"name": "harbor-ui",
|
||||||
"version": "0.6.22",
|
"version": "0.6.25",
|
||||||
"description": "Harbor shared UI components based on Clarity and Angular4",
|
"description": "Harbor shared UI components based on Clarity and Angular4",
|
||||||
"author": "VMware",
|
"author": "VMware",
|
||||||
"module": "index.js",
|
"module": "index.js",
|
||||||
|
@ -65,6 +65,10 @@ export class Configuration {
|
|||||||
ldap_uid: StringValueItem;
|
ldap_uid: StringValueItem;
|
||||||
ldap_url: StringValueItem;
|
ldap_url: StringValueItem;
|
||||||
ldap_verify_cert: BoolValueItem;
|
ldap_verify_cert: BoolValueItem;
|
||||||
|
uaa_client_id: StringValueItem;
|
||||||
|
uaa_client_secret?: StringValueItem;
|
||||||
|
uaa_endpoint: StringValueItem;
|
||||||
|
uaa_verify_cert: BoolValueItem;
|
||||||
email_host: StringValueItem;
|
email_host: StringValueItem;
|
||||||
email_identity: StringValueItem;
|
email_identity: StringValueItem;
|
||||||
email_from: StringValueItem;
|
email_from: StringValueItem;
|
||||||
@ -91,6 +95,10 @@ export class Configuration {
|
|||||||
this.ldap_uid = new StringValueItem("", true);
|
this.ldap_uid = new StringValueItem("", true);
|
||||||
this.ldap_url = new StringValueItem("", true);
|
this.ldap_url = new StringValueItem("", true);
|
||||||
this.ldap_verify_cert = new BoolValueItem(true, true);
|
this.ldap_verify_cert = new BoolValueItem(true, true);
|
||||||
|
this.uaa_client_id = new StringValueItem("", true);
|
||||||
|
this.uaa_client_secret = new StringValueItem("", true);
|
||||||
|
this.uaa_endpoint = new StringValueItem("", true);
|
||||||
|
this.uaa_verify_cert = new BoolValueItem(false, true);
|
||||||
this.email_host = new StringValueItem("", true);
|
this.email_host = new StringValueItem("", true);
|
||||||
this.email_identity = new StringValueItem("", true);
|
this.email_identity = new StringValueItem("", true);
|
||||||
this.email_from = new StringValueItem("", true);
|
this.email_from = new StringValueItem("", true);
|
||||||
|
@ -9,18 +9,15 @@
|
|||||||
"check-space"
|
"check-space"
|
||||||
],
|
],
|
||||||
"curly": true,
|
"curly": true,
|
||||||
"eofline": true,
|
"eofline": false,
|
||||||
"forin": true,
|
"forin": false,
|
||||||
"indent": [
|
"indent": [
|
||||||
true,
|
true,
|
||||||
"spaces"
|
"spaces"
|
||||||
],
|
],
|
||||||
"label-position": true,
|
"label-position": true,
|
||||||
"label-undefined": true,
|
"label-undefined": true,
|
||||||
"max-line-length": [
|
"max-line-length": false,
|
||||||
false,
|
|
||||||
140
|
|
||||||
],
|
|
||||||
"member-access": false,
|
"member-access": false,
|
||||||
"member-ordering": [
|
"member-ordering": [
|
||||||
true,
|
true,
|
||||||
@ -74,7 +71,8 @@
|
|||||||
],
|
],
|
||||||
"quotemark": [
|
"quotemark": [
|
||||||
true,
|
true,
|
||||||
"single"
|
"double",
|
||||||
|
"avoid-escape"
|
||||||
],
|
],
|
||||||
"radix": true,
|
"radix": true,
|
||||||
"semicolon": [
|
"semicolon": [
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
"clarity-icons": "^0.10.17",
|
"clarity-icons": "^0.10.17",
|
||||||
"clarity-ui": "^0.10.17",
|
"clarity-ui": "^0.10.17",
|
||||||
"core-js": "^2.4.1",
|
"core-js": "^2.4.1",
|
||||||
"harbor-ui": "0.6.25-dev.3",
|
"harbor-ui": "0.6.25",
|
||||||
"intl": "^1.2.5",
|
"intl": "^1.2.5",
|
||||||
"mutationobserver-shim": "^0.3.2",
|
"mutationobserver-shim": "^0.3.2",
|
||||||
"ngx-cookie": "^1.0.0",
|
"ngx-cookie": "^1.0.0",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<clr-modal [(clrModalOpen)]="opened" [clrModalStaticBackdrop]="staticBackdrop" [clrModalClosable]="false">
|
<clr-modal [(clrModalOpen)]="opened" [clrModalStaticBackdrop]="staticBackdrop" [clrModalClosable]="false">
|
||||||
<h3 class="modal-title">{{'PROFILE.TITLE' | translate}}</h3>
|
<h3 class="modal-title">{{'PROFILE.TITLE' | translate}}</h3>
|
||||||
<inline-alert class="modal-title" (confirmEvt)="confirm($event)"></inline-alert>
|
<inline-alert class="modal-title" (confirmEvt)="confirmYes($event)" (closeEvt)="confirmNo($event)"></inline-alert>
|
||||||
<div class="modal-body" style="overflow-y: hidden;">
|
<div class="modal-body" style="overflow-y: hidden;">
|
||||||
<form #accountSettingsFrom="ngForm" class="form">
|
<form #accountSettingsFrom="ngForm" class="form">
|
||||||
<section class="form-block">
|
<section class="form-block">
|
||||||
|
@ -240,8 +240,13 @@ export class AccountSettingsModalComponent implements OnInit, AfterViewChecked {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
confirm($event: any): void {
|
confirmNo($event: any): void {
|
||||||
if(this.RenameOnGoing) {
|
if (this.RenameOnGoing) {
|
||||||
|
this.RenameOnGoing = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
confirmYes($event: any): void {
|
||||||
|
if (this.RenameOnGoing) {
|
||||||
this.confirmRename();
|
this.confirmRename();
|
||||||
this.RenameOnGoing = false;
|
this.RenameOnGoing = false;
|
||||||
}
|
}
|
||||||
|
@ -165,7 +165,7 @@
|
|||||||
<clr-checkbox name="selfReg" id="selfReg" [(ngModel)]="currentConfig.self_registration.value" [disabled]="disabled(currentConfig.self_registration)">
|
<clr-checkbox name="selfReg" id="selfReg" [(ngModel)]="currentConfig.self_registration.value" [disabled]="disabled(currentConfig.self_registration)">
|
||||||
<a href="javascript:void(0)" role="tooltip" aria-haspopup="true" class="tooltip tooltip-top-right" style="top:-7px;">
|
<a href="javascript:void(0)" role="tooltip" aria-haspopup="true" class="tooltip tooltip-top-right" style="top:-7px;">
|
||||||
<clr-icon shape="info-circle" class="info-tips-icon" size="24"></clr-icon>
|
<clr-icon shape="info-circle" class="info-tips-icon" size="24"></clr-icon>
|
||||||
<span *ngIf="checkboxenable; else elseBlock" class="tooltip-content">{{'CONFIG.TOOLTIP.SELF_REGISTRATION_ENABLE' | translate}}</span>
|
<span *ngIf="checkable; else elseBlock" class="tooltip-content">{{'CONFIG.TOOLTIP.SELF_REGISTRATION_ENABLE' | translate}}</span>
|
||||||
<ng-template #elseBlock><span class="tooltip-content">{{'CONFIG.TOOLTIP.SELF_REGISTRATION_DISABLE' | translate}}</span></ng-template>
|
<ng-template #elseBlock><span class="tooltip-content">{{'CONFIG.TOOLTIP.SELF_REGISTRATION_DISABLE' | translate}}</span></ng-template>
|
||||||
</a>
|
</a>
|
||||||
</clr-checkbox>
|
</clr-checkbox>
|
||||||
|
@ -19,15 +19,16 @@ import { Configuration } from 'harbor-ui';
|
|||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'config-auth',
|
selector: 'config-auth',
|
||||||
templateUrl: "config-auth.component.html",
|
templateUrl: 'config-auth.component.html',
|
||||||
styleUrls: ['../config.component.css']
|
styleUrls: ['../config.component.css']
|
||||||
})
|
})
|
||||||
export class ConfigurationAuthComponent implements OnChanges {
|
export class ConfigurationAuthComponent implements OnChanges {
|
||||||
changeSub: Subscription;
|
changeSub: Subscription;
|
||||||
@Input("allConfig") currentConfig: Configuration = new Configuration();
|
@Input('allConfig') currentConfig: Configuration = new Configuration();
|
||||||
|
|
||||||
@ViewChild("authConfigFrom") authForm: NgForm;
|
@ViewChild('authConfigFrom') authForm: NgForm;
|
||||||
|
|
||||||
|
constructor() { }
|
||||||
ngOnChanges(): void {
|
ngOnChanges(): void {
|
||||||
if ( this.currentConfig &&
|
if ( this.currentConfig &&
|
||||||
this.currentConfig.auth_mode &&
|
this.currentConfig.auth_mode &&
|
||||||
@ -36,14 +37,12 @@ export class ConfigurationAuthComponent implements OnChanges {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get checkboxenable(){
|
get checkable(){
|
||||||
return this.currentConfig &&
|
return this.currentConfig &&
|
||||||
this.currentConfig.self_registration &&
|
this.currentConfig.self_registration &&
|
||||||
this.currentConfig.self_registration.value === true;
|
this.currentConfig.self_registration.value === true;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor() { }
|
|
||||||
|
|
||||||
public get showLdap(): boolean {
|
public get showLdap(): boolean {
|
||||||
return this.currentConfig &&
|
return this.currentConfig &&
|
||||||
this.currentConfig.auth_mode &&
|
this.currentConfig.auth_mode &&
|
||||||
@ -62,6 +61,10 @@ export class ConfigurationAuthComponent implements OnChanges {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public isValid(): boolean {
|
||||||
|
return this.authForm && this.authForm.valid;
|
||||||
|
}
|
||||||
|
|
||||||
setVerifyCertValue($event: any) {
|
setVerifyCertValue($event: any) {
|
||||||
this.currentConfig.ldap_verify_cert.value = $event;
|
this.currentConfig.ldap_verify_cert.value = $event;
|
||||||
}
|
}
|
||||||
@ -70,16 +73,12 @@ export class ConfigurationAuthComponent implements OnChanges {
|
|||||||
return !(prop && prop.editable);
|
return !(prop && prop.editable);
|
||||||
}
|
}
|
||||||
|
|
||||||
public isValid(): boolean {
|
|
||||||
return this.authForm && this.authForm.valid;
|
|
||||||
}
|
|
||||||
|
|
||||||
handleOnChange($event: any): void {
|
handleOnChange($event: any): void {
|
||||||
if ($event && $event.target && $event.target["value"]) {
|
if ($event && $event.target && $event.target["value"]) {
|
||||||
let authMode = $event.target["value"];
|
let authMode = $event.target["value"];
|
||||||
if (authMode === 'ldap_auth' || authMode === 'uaa_auth') {
|
if (authMode === 'ldap_auth' || authMode === 'uaa_auth') {
|
||||||
if (this.currentConfig.self_registration.value) {
|
if (this.currentConfig.self_registration.value) {
|
||||||
this.currentConfig.self_registration.value = false;//uncheck
|
this.currentConfig.self_registration.value = false; // uncheck
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,62 +0,0 @@
|
|||||||
<div class="config-container">
|
|
||||||
<h2 style="display: inline-block;" class="custom-h2">{{'CONFIG.TITLE' | translate }}</h2>
|
|
||||||
<span class="spinner spinner-inline" [hidden]="inProgress === false"></span>
|
|
||||||
<clr-tabs (clrTabsCurrentTabLinkChanged)="tabLinkChanged($event)">
|
|
||||||
<clr-tab-link [clrTabLinkId]="'config-auth'" [clrTabLinkActive]='isCurrentTabLink("config-auth")'>{{'CONFIG.AUTH' | translate }}</clr-tab-link>
|
|
||||||
<clr-tab-link [clrTabLinkId]="'config-replication'" [clrTabLinkActive]='isCurrentTabLink("config-replication")'>{{'CONFIG.REPLICATION' | translate }}</clr-tab-link>
|
|
||||||
<clr-tab-link [clrTabLinkId]="'config-email'" [clrTabLinkActive]='isCurrentTabLink("config-email")'>{{'CONFIG.EMAIL' | translate }}</clr-tab-link>
|
|
||||||
<clr-tab-link [clrTabLinkId]="'config-system'" [clrTabLinkActive]='isCurrentTabLink("config-system")'>{{'CONFIG.SYSTEM' | translate }}</clr-tab-link>
|
|
||||||
|
|
||||||
<clr-tab-content [clrTabContentId]="'authentication'" [clrTabContentActive]='isCurrentTabContent("authentication")'>
|
|
||||||
<config-auth [ldapConfig]="allConfig"></config-auth>
|
|
||||||
</clr-tab-content>
|
|
||||||
<clr-tab-content [clrTabContentId]="'replication'" [clrTabContentActive]='isCurrentTabContent("replication")'>
|
|
||||||
<form #repoConfigFrom="ngForm" class="form">
|
|
||||||
<section class="form-block">
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="verifyRemoteCert">{{'CONFIG.VERIFY_REMOTE_CERT' | translate }}</label>
|
|
||||||
<clr-checkbox name="verifyRemoteCert" id="verifyRemoteCert" [(ngModel)]="allConfig.verify_remote_cert.value" [disabled]="disabled(allConfig.verify_remote_cert)">
|
|
||||||
<a href="javascript:void(0)" role="tooltip" aria-haspopup="true" class="tooltip tooltip-lg tooltip-top-right" style="top:-8px;">
|
|
||||||
<clr-icon shape="info-circle" class="is-info" size="24"></clr-icon>
|
|
||||||
<span class="tooltip-content">{{'CONFIG.TOOLTIP.VERIFY_REMOTE_CERT' | translate }}</span>
|
|
||||||
</a>
|
|
||||||
</clr-checkbox>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</form>
|
|
||||||
</clr-tab-content>
|
|
||||||
<clr-tab-content [clrTabContentId]="'email'" [clrTabContentActive]='isCurrentTabContent("email")'>
|
|
||||||
<config-email [mailConfig]="allConfig"></config-email>
|
|
||||||
</clr-tab-content>
|
|
||||||
<clr-tab-content [clrTabContentId]="'system_settings'" [clrTabContentActive]='isCurrentTabContent("system_settings")'>
|
|
||||||
<form #systemConfigFrom="ngForm" class="form">
|
|
||||||
<section class="form-block">
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="tokenExpiration" class="required">{{'CONFIG.TOKEN_EXPIRATION' | translate}}</label>
|
|
||||||
<label for="tokenExpiration" aria-haspopup="true" role="tooltip" class="tooltip tooltip-validation tooltip-md tooltip-top-right" [class.invalid]="tokenExpirationInput.invalid && (tokenExpirationInput.dirty || tokenExpirationInput.touched)">
|
|
||||||
<input name="tokenExpiration" type="text" #tokenExpirationInput="ngModel" [(ngModel)]="allConfig.token_expiration.value"
|
|
||||||
required
|
|
||||||
pattern="^[1-9]{1}[\d]*$"
|
|
||||||
id="tokenExpiration"
|
|
||||||
size="40" [disabled]="disabled(allConfig.token_expiration)">
|
|
||||||
<span class="tooltip-content">
|
|
||||||
{{'TOOLTIP.NUMBER_REQUIRED' | translate}}
|
|
||||||
</span>
|
|
||||||
</label>
|
|
||||||
<a href="javascript:void(0)" role="tooltip" aria-haspopup="true" class="tooltip tooltip-top-right">
|
|
||||||
<clr-icon shape="info-circle" class="is-info" size="24"></clr-icon>
|
|
||||||
<span class="tooltip-content">{{'CONFIG.TOOLTIP.TOKEN_EXPIRATION' | translate}}</span>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</form>
|
|
||||||
</clr-tab-content>
|
|
||||||
</clr-tabs>
|
|
||||||
<div>
|
|
||||||
<button type="button" class="btn btn-primary" (click)="save()" [disabled]="!isValid() || !hasChanges()">{{'BUTTON.SAVE' | translate}}</button>
|
|
||||||
<button type="button" class="btn btn-outline" (click)="cancel()" [disabled]="!isValid() || !hasChanges()">{{'BUTTON.CANCEL' | translate}}</button>
|
|
||||||
<button type="button" class="btn btn-outline" (click)="testMailServer()" *ngIf="showTestServerBtn" [disabled]="!isMailConfigValid()">{{'BUTTON.TEST_MAIL' | translate}}</button>
|
|
||||||
<button type="button" class="btn btn-outline" (click)="testLDAPServer()" *ngIf="showLdapServerBtn" [disabled]="!isLDAPConfigValid()">{{'BUTTON.TEST_LDAP' | translate}}</button>
|
|
||||||
<span class="spinner spinner-inline" [hidden]="!testingInProgress"></span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
@ -1,24 +1,23 @@
|
|||||||
// Copyright (c) 2017 VMware, Inc. All Rights Reserved.
|
// Copyright (c) 2017 VMware, Inc. All Rights Reserved.
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the 'License');
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
// You may obtain a copy of the License at
|
// You may obtain a copy of the License at
|
||||||
//
|
//
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
//
|
//
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
// distributed under the License is distributed on an 'AS IS' BASIS,
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core';
|
import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core';
|
||||||
import { Router } from '@angular/router';
|
|
||||||
|
|
||||||
import { ConfigurationService } from './config.service';
|
import { ConfigurationService } from './config.service';
|
||||||
import { ConfirmationTargets, ConfirmationState } from '../shared/shared.const';;
|
import { ConfirmationTargets, ConfirmationState } from '../shared/shared.const';
|
||||||
import { ConfirmationDialogService } from '../shared/confirmation-dialog/confirmation-dialog.service';
|
import { ConfirmationDialogService } from '../shared/confirmation-dialog/confirmation-dialog.service';
|
||||||
import { Subscription } from 'rxjs/Subscription';
|
import { Subscription } from 'rxjs/Subscription';
|
||||||
import { ConfirmationMessage } from '../shared/confirmation-dialog/confirmation-message'
|
import { ConfirmationMessage } from '../shared/confirmation-dialog/confirmation-message';
|
||||||
|
|
||||||
import { ConfigurationAuthComponent } from './auth/config-auth.component';
|
import { ConfigurationAuthComponent } from './auth/config-auth.component';
|
||||||
import { ConfigurationEmailComponent } from './email/config-email.component';
|
import { ConfigurationEmailComponent } from './email/config-email.component';
|
||||||
@ -29,24 +28,22 @@ import { MessageHandlerService } from '../shared/message-handler/message-handler
|
|||||||
import {
|
import {
|
||||||
Configuration,
|
Configuration,
|
||||||
StringValueItem,
|
StringValueItem,
|
||||||
ComplexValueItem,
|
|
||||||
SystemSettingsComponent,
|
SystemSettingsComponent,
|
||||||
VulnerabilityConfigComponent,
|
VulnerabilityConfigComponent,
|
||||||
ClairDBStatus
|
|
||||||
} from 'harbor-ui';
|
} from 'harbor-ui';
|
||||||
|
|
||||||
const fakePass = "aWpLOSYkIzJTTU4wMDkx";
|
const fakePass = 'aWpLOSYkIzJTTU4wMDkx';
|
||||||
const TabLinkContentMap = {
|
const TabLinkContentMap = {
|
||||||
"config-auth": "authentication",
|
'config-auth': 'authentication',
|
||||||
"config-replication": "replication",
|
'config-replication': 'replication',
|
||||||
"config-email": "email",
|
'config-email': 'email',
|
||||||
"config-system": "system_settings",
|
'config-system': 'system_settings',
|
||||||
"config-vulnerability": "vulnerability"
|
'config-vulnerability': 'vulnerability'
|
||||||
};
|
};
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'config',
|
selector: 'config',
|
||||||
templateUrl: "config.component.html",
|
templateUrl: 'config.component.html',
|
||||||
styleUrls: ['config.component.css']
|
styleUrls: ['config.component.css']
|
||||||
})
|
})
|
||||||
export class ConfigurationComponent implements OnInit, OnDestroy {
|
export class ConfigurationComponent implements OnInit, OnDestroy {
|
||||||
@ -99,36 +96,36 @@ export class ConfigurationComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
let properties = [];
|
let properties = [];
|
||||||
switch (this.currentTabId) {
|
switch (this.currentTabId) {
|
||||||
case "config-auth":
|
case 'config-auth':
|
||||||
for (let prop in allChanges) {
|
for (let prop in allChanges) {
|
||||||
if (prop.startsWith("ldap_")) {
|
if (prop.startsWith('ldap_')) {
|
||||||
return allChanges;
|
return allChanges;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
properties = ["auth_mode", "project_creation_restriction", "self_registration"];
|
properties = ['auth_mode', 'project_creation_restriction', 'self_registration'];
|
||||||
break;
|
break;
|
||||||
case "config-email":
|
case 'config-email':
|
||||||
for (let prop in allChanges) {
|
for (let prop in allChanges) {
|
||||||
if (prop.startsWith("email_")) {
|
if (prop.startsWith('email_')) {
|
||||||
return allChanges;
|
return allChanges;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
case "config-replication":
|
case 'config-replication':
|
||||||
properties = ["verify_remote_cert"];
|
properties = ['verify_remote_cert'];
|
||||||
break;
|
break;
|
||||||
case "config-system":
|
case 'config-system':
|
||||||
properties = ["token_expiration"];
|
properties = ['token_expiration'];
|
||||||
break;
|
break;
|
||||||
case "config-vulnerability":
|
case 'config-vulnerability':
|
||||||
properties = ["scan_all_policy"];
|
properties = ['scan_all_policy'];
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let prop in allChanges) {
|
for (let prop in allChanges) {
|
||||||
if (properties.indexOf(prop) != -1) {
|
if (properties.indexOf(prop) !== -1) {
|
||||||
return allChanges;
|
return allChanges;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -137,8 +134,8 @@ export class ConfigurationComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
//First load
|
// First load
|
||||||
//Double confirm the current use has admin role
|
// Double confirm the current use has admin role
|
||||||
let currentUser = this.session.getCurrentUser();
|
let currentUser = this.session.getCurrentUser();
|
||||||
if (currentUser && currentUser.has_admin_role > 0) {
|
if (currentUser && currentUser.has_admin_role > 0) {
|
||||||
this.retrieveConfig();
|
this.retrieveConfig();
|
||||||
@ -150,8 +147,8 @@ export class ConfigurationComponent implements OnInit, OnDestroy {
|
|||||||
if (confirmation.source === ConfirmationTargets.CONFIG) {
|
if (confirmation.source === ConfirmationTargets.CONFIG) {
|
||||||
this.reset(confirmation.data);
|
this.reset(confirmation.data);
|
||||||
} else if (confirmation.source === ConfirmationTargets.CONFIG_TAB) {
|
} else if (confirmation.source === ConfirmationTargets.CONFIG_TAB) {
|
||||||
this.reset(confirmation.data["changes"]);
|
this.reset(confirmation.data['changes']);
|
||||||
this.currentTabId = confirmation.data["tabId"];
|
this.currentTabId = confirmation.data['tabId'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -200,7 +197,7 @@ export class ConfigurationComponent implements OnInit, OnDestroy {
|
|||||||
public get showLdapServerBtn(): boolean {
|
public get showLdapServerBtn(): boolean {
|
||||||
return this.currentTabId === 'config-auth' &&
|
return this.currentTabId === 'config-auth' &&
|
||||||
this.allConfig.auth_mode &&
|
this.allConfig.auth_mode &&
|
||||||
this.allConfig.auth_mode.value === "ldap_auth";
|
this.allConfig.auth_mode.value === 'ldap_auth';
|
||||||
}
|
}
|
||||||
|
|
||||||
public get hideMailTestingSpinner(): boolean {
|
public get hideMailTestingSpinner(): boolean {
|
||||||
@ -218,7 +215,7 @@ export class ConfigurationComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public tabLinkClick(tabLink: string) {
|
public tabLinkClick(tabLink: string) {
|
||||||
//Whether has unsaved changes in current tab
|
// Whether has unsaved changes in current tab
|
||||||
let changes = this.hasUnsavedChangesOfCurrentTab();
|
let changes = this.hasUnsavedChangesOfCurrentTab();
|
||||||
if (!changes) {
|
if (!changes) {
|
||||||
this.currentTabId = tabLink;
|
this.currentTabId = tabLink;
|
||||||
@ -229,18 +226,18 @@ export class ConfigurationComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Save the changed values
|
* Save the changed values
|
||||||
*
|
*
|
||||||
* @memberOf ConfigurationComponent
|
* @memberOf ConfigurationComponent
|
||||||
*/
|
*/
|
||||||
public save(): void {
|
public save(): void {
|
||||||
let changes = this.getChanges();
|
let changes = this.getChanges();
|
||||||
if (!this.isEmpty(changes)) {
|
if (!this.isEmpty(changes)) {
|
||||||
//Fix policy parameters issue
|
// Fix policy parameters issue
|
||||||
let scanningAllPolicy = changes["scan_all_policy"];
|
let scanningAllPolicy = changes['scan_all_policy'];
|
||||||
if (scanningAllPolicy &&
|
if (scanningAllPolicy &&
|
||||||
scanningAllPolicy.type !== "daily" &&
|
scanningAllPolicy.type !== 'daily' &&
|
||||||
scanningAllPolicy.parameters) {
|
scanningAllPolicy.parameters) {
|
||||||
delete (scanningAllPolicy.parameters);
|
delete (scanningAllPolicy.parameters);
|
||||||
}
|
}
|
||||||
@ -249,32 +246,32 @@ export class ConfigurationComponent implements OnInit, OnDestroy {
|
|||||||
this.configService.saveConfiguration(changes)
|
this.configService.saveConfiguration(changes)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
this.onGoing = false;
|
this.onGoing = false;
|
||||||
//API should return the updated configurations here
|
// API should return the updated configurations here
|
||||||
//Unfortunately API does not do that
|
// Unfortunately API does not do that
|
||||||
//To refresh the view, we can clone the original data copy
|
// To refresh the view, we can clone the original data copy
|
||||||
//or force refresh by calling service.
|
// or force refresh by calling service.
|
||||||
//HERE we choose force way
|
// HERE we choose force way
|
||||||
this.retrieveConfig();
|
this.retrieveConfig();
|
||||||
|
|
||||||
//Reload bootstrap option
|
// Reload bootstrap option
|
||||||
this.appConfigService.load().catch(error => console.error("Failed to reload bootstrap option with error: ", error));
|
this.appConfigService.load().catch(error => console.error('Failed to reload bootstrap option with error: ', error));
|
||||||
|
|
||||||
this.msgHandler.showSuccess("CONFIG.SAVE_SUCCESS");
|
this.msgHandler.showSuccess('CONFIG.SAVE_SUCCESS');
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
this.onGoing = false;
|
this.onGoing = false;
|
||||||
this.msgHandler.handleError(error);
|
this.msgHandler.handleError(error);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
//Inprop situation, should not come here
|
// Inprop situation, should not come here
|
||||||
console.error("Save obort becasue nothing changed");
|
console.error('Save obort becasue nothing changed');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Discard current changes if have and reset
|
* Discard current changes if have and reset
|
||||||
*
|
*
|
||||||
* @memberOf ConfigurationComponent
|
* @memberOf ConfigurationComponent
|
||||||
*/
|
*/
|
||||||
public cancel(): void {
|
public cancel(): void {
|
||||||
@ -282,98 +279,98 @@ export class ConfigurationComponent implements OnInit, OnDestroy {
|
|||||||
if (!this.isEmpty(changes)) {
|
if (!this.isEmpty(changes)) {
|
||||||
this.confirmUnsavedChanges(changes);
|
this.confirmUnsavedChanges(changes);
|
||||||
} else {
|
} else {
|
||||||
//Invalid situation, should not come here
|
// Invalid situation, should not come here
|
||||||
console.error("Nothing changed");
|
console.error('Nothing changed');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Test the connection of specified mail server
|
* Test the connection of specified mail server
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* @memberOf ConfigurationComponent
|
* @memberOf ConfigurationComponent
|
||||||
*/
|
*/
|
||||||
public testMailServer(): void {
|
public testMailServer(): void {
|
||||||
if (this.testingMailOnGoing) {
|
if (this.testingMailOnGoing) {
|
||||||
return;//Should not come here
|
return; // Should not come here
|
||||||
}
|
}
|
||||||
let mailSettings = {};
|
let mailSettings = {};
|
||||||
for (let prop in this.allConfig) {
|
for (let prop in this.allConfig) {
|
||||||
if (prop.startsWith("email_")) {
|
if (prop.startsWith('email_')) {
|
||||||
mailSettings[prop] = this.allConfig[prop].value;
|
mailSettings[prop] = this.allConfig[prop].value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//Confirm port is number
|
// Confirm port is number
|
||||||
mailSettings["email_port"] = +mailSettings["email_port"];
|
mailSettings['email_port'] = +mailSettings['email_port'];
|
||||||
let allChanges = this.getChanges();
|
let allChanges = this.getChanges();
|
||||||
let password = allChanges["email_password"]
|
let password = allChanges['email_password'];
|
||||||
if (password) {
|
if (password) {
|
||||||
mailSettings["email_password"] = password;
|
mailSettings['email_password'] = password;
|
||||||
} else {
|
} else {
|
||||||
delete mailSettings["email_password"];
|
delete mailSettings['email_password'];
|
||||||
}
|
}
|
||||||
|
|
||||||
this.testingMailOnGoing = true;
|
this.testingMailOnGoing = true;
|
||||||
this.configService.testMailServer(mailSettings)
|
this.configService.testMailServer(mailSettings)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
this.testingMailOnGoing = false;
|
this.testingMailOnGoing = false;
|
||||||
this.msgHandler.showSuccess("CONFIG.TEST_MAIL_SUCCESS");
|
this.msgHandler.showSuccess('CONFIG.TEST_MAIL_SUCCESS');
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
this.testingMailOnGoing = false;
|
this.testingMailOnGoing = false;
|
||||||
let err = error._body;
|
let err = error._body;
|
||||||
if (!err) {
|
if (!err) {
|
||||||
err = "UNKNOWN";
|
err = 'UNKNOWN';
|
||||||
}
|
}
|
||||||
this.msgHandler.showError("CONFIG.TEST_MAIL_FAILED", { 'param': err });
|
this.msgHandler.showError('CONFIG.TEST_MAIL_FAILED', { 'param': err });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public testLDAPServer(): void {
|
public testLDAPServer(): void {
|
||||||
if (this.testingLDAPOnGoing) {
|
if (this.testingLDAPOnGoing) {
|
||||||
return;//Should not come here
|
return; // Should not come here
|
||||||
}
|
}
|
||||||
|
|
||||||
let ldapSettings = {};
|
let ldapSettings = {};
|
||||||
for (let prop in this.allConfig) {
|
for (let prop in this.allConfig) {
|
||||||
if (prop.startsWith("ldap_")) {
|
if (prop.startsWith('ldap_')) {
|
||||||
ldapSettings[prop] = this.allConfig[prop].value;
|
ldapSettings[prop] = this.allConfig[prop].value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let allChanges = this.getChanges();
|
let allChanges = this.getChanges();
|
||||||
let ldapSearchPwd = allChanges["ldap_search_password"];
|
let ldapSearchPwd = allChanges['ldap_search_password'];
|
||||||
if (ldapSearchPwd) {
|
if (ldapSearchPwd) {
|
||||||
ldapSettings['ldap_search_password'] = ldapSearchPwd;
|
ldapSettings['ldap_search_password'] = ldapSearchPwd;
|
||||||
} else {
|
} else {
|
||||||
delete ldapSettings['ldap_search_password'];
|
delete ldapSettings['ldap_search_password'];
|
||||||
}
|
}
|
||||||
|
|
||||||
//Fix: Confirm ldap scope is number
|
// Fix: Confirm ldap scope is number
|
||||||
ldapSettings['ldap_scope'] = +ldapSettings['ldap_scope'];
|
ldapSettings['ldap_scope'] = +ldapSettings['ldap_scope'];
|
||||||
|
|
||||||
this.testingLDAPOnGoing = true;
|
this.testingLDAPOnGoing = true;
|
||||||
this.configService.testLDAPServer(ldapSettings)
|
this.configService.testLDAPServer(ldapSettings)
|
||||||
.then(respone => {
|
.then(respone => {
|
||||||
this.testingLDAPOnGoing = false;
|
this.testingLDAPOnGoing = false;
|
||||||
this.msgHandler.showSuccess("CONFIG.TEST_LDAP_SUCCESS");
|
this.msgHandler.showSuccess('CONFIG.TEST_LDAP_SUCCESS');
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
this.testingLDAPOnGoing = false;
|
this.testingLDAPOnGoing = false;
|
||||||
let err = error._body;
|
let err = error._body;
|
||||||
if (!err) {
|
if (!err) {
|
||||||
err = "UNKNOWN";
|
err = 'UNKNOWN';
|
||||||
}
|
}
|
||||||
this.msgHandler.showError("CONFIG.TEST_LDAP_FAILED", { 'param': err });
|
this.msgHandler.showError('CONFIG.TEST_LDAP_FAILED', { 'param': err });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
confirmUnsavedChanges(changes: any) {
|
confirmUnsavedChanges(changes: any) {
|
||||||
let msg = new ConfirmationMessage(
|
let msg = new ConfirmationMessage(
|
||||||
"CONFIG.CONFIRM_TITLE",
|
'CONFIG.CONFIRM_TITLE',
|
||||||
"CONFIG.CONFIRM_SUMMARY",
|
'CONFIG.CONFIRM_SUMMARY',
|
||||||
"",
|
'',
|
||||||
changes,
|
changes,
|
||||||
ConfirmationTargets.CONFIG
|
ConfirmationTargets.CONFIG
|
||||||
);
|
);
|
||||||
@ -383,12 +380,12 @@ export class ConfigurationComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
confirmUnsavedTabChanges(changes: any, tabId: string) {
|
confirmUnsavedTabChanges(changes: any, tabId: string) {
|
||||||
let msg = new ConfirmationMessage(
|
let msg = new ConfirmationMessage(
|
||||||
"CONFIG.CONFIRM_TITLE",
|
'CONFIG.CONFIRM_TITLE',
|
||||||
"CONFIG.CONFIRM_SUMMARY",
|
'CONFIG.CONFIRM_SUMMARY',
|
||||||
"",
|
'',
|
||||||
{
|
{
|
||||||
"changes": changes,
|
'changes': changes,
|
||||||
"tabId": tabId
|
'tabId': tabId
|
||||||
},
|
},
|
||||||
ConfirmationTargets.CONFIG_TAB
|
ConfirmationTargets.CONFIG_TAB
|
||||||
);
|
);
|
||||||
@ -402,12 +399,12 @@ export class ConfigurationComponent implements OnInit, OnDestroy {
|
|||||||
.then((configurations: Configuration) => {
|
.then((configurations: Configuration) => {
|
||||||
this.onGoing = false;
|
this.onGoing = false;
|
||||||
|
|
||||||
//Add two password fields
|
// Add two password fields
|
||||||
configurations.email_password = new StringValueItem(fakePass, true);
|
configurations.email_password = new StringValueItem(fakePass, true);
|
||||||
configurations.ldap_search_password = new StringValueItem(fakePass, true);
|
configurations.ldap_search_password = new StringValueItem(fakePass, true);
|
||||||
configurations.uaa_client_secret = new StringValueItem(fakePass, false);
|
configurations.uaa_client_secret = new StringValueItem(fakePass, true);
|
||||||
this.allConfig = configurations;
|
this.allConfig = configurations;
|
||||||
//Keep the original copy of the data
|
// Keep the original copy of the data
|
||||||
this.originalCopy = this.clone(configurations);
|
this.originalCopy = this.clone(configurations);
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
@ -417,12 +414,12 @@ export class ConfigurationComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Get the changed fields and return a map
|
* Get the changed fields and return a map
|
||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
* @returns {*}
|
* @returns {*}
|
||||||
*
|
*
|
||||||
* @memberOf ConfigurationComponent
|
* @memberOf ConfigurationComponent
|
||||||
*/
|
*/
|
||||||
getChanges(): { [key: string]: any | any[] } {
|
getChanges(): { [key: string]: any | any[] } {
|
||||||
@ -435,13 +432,13 @@ export class ConfigurationComponent implements OnInit, OnDestroy {
|
|||||||
if (field && field.editable) {
|
if (field && field.editable) {
|
||||||
if (!this.compareValue(field.value, this.allConfig[prop].value)) {
|
if (!this.compareValue(field.value, this.allConfig[prop].value)) {
|
||||||
changes[prop] = this.allConfig[prop].value;
|
changes[prop] = this.allConfig[prop].value;
|
||||||
//Number
|
// Number
|
||||||
if (typeof field.value === "number") {
|
if (typeof field.value === 'number') {
|
||||||
changes[prop] = +changes[prop];
|
changes[prop] = +changes[prop];
|
||||||
}
|
}
|
||||||
|
|
||||||
//Trim string value
|
// Trim string value
|
||||||
if (typeof field.value === "string") {
|
if (typeof field.value === 'string') {
|
||||||
changes[prop] = ('' + changes[prop]).trim();
|
changes[prop] = ('' + changes[prop]).trim();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -451,44 +448,44 @@ export class ConfigurationComponent implements OnInit, OnDestroy {
|
|||||||
return changes;
|
return changes;
|
||||||
}
|
}
|
||||||
|
|
||||||
//private
|
// private
|
||||||
compareValue(a: any, b: any): boolean {
|
compareValue(a: any, b: any): boolean {
|
||||||
if ((a && !b) || (!a && b)) return false;
|
if ((a && !b) || (!a && b)) { return false; };
|
||||||
if (!a && !b) return true;
|
if (!a && !b) { return true; };
|
||||||
|
|
||||||
return JSON.stringify(a) === JSON.stringify(b);
|
return JSON.stringify(a) === JSON.stringify(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
//private
|
// private
|
||||||
isEmpty(obj: any): boolean {
|
isEmpty(obj: any): boolean {
|
||||||
return !obj || JSON.stringify(obj) === "{}";
|
return !obj || JSON.stringify(obj) === '{}';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Deep clone the configuration object
|
* Deep clone the configuration object
|
||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
* @param {Configuration} src
|
* @param {Configuration} src
|
||||||
* @returns {Configuration}
|
* @returns {Configuration}
|
||||||
*
|
*
|
||||||
* @memberOf ConfigurationComponent
|
* @memberOf ConfigurationComponent
|
||||||
*/
|
*/
|
||||||
clone(src: Configuration): Configuration {
|
clone(src: Configuration): Configuration {
|
||||||
if (!src) {
|
if (!src) {
|
||||||
return new Configuration();//Empty
|
return new Configuration(); // Empty
|
||||||
}
|
}
|
||||||
|
|
||||||
return JSON.parse(JSON.stringify(src));
|
return JSON.parse(JSON.stringify(src));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Reset the configuration form
|
* Reset the configuration form
|
||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
* @param {*} changes
|
* @param {*} changes
|
||||||
*
|
*
|
||||||
* @memberOf ConfigurationComponent
|
* @memberOf ConfigurationComponent
|
||||||
*/
|
*/
|
||||||
reset(changes: any): void {
|
reset(changes: any): void {
|
||||||
@ -496,11 +493,10 @@ export class ConfigurationComponent implements OnInit, OnDestroy {
|
|||||||
for (let prop in changes) {
|
for (let prop in changes) {
|
||||||
if (this.originalCopy[prop]) {
|
if (this.originalCopy[prop]) {
|
||||||
this.allConfig[prop] = this.clone(this.originalCopy[prop]);
|
this.allConfig[prop] = this.clone(this.originalCopy[prop]);
|
||||||
//this.allConfig[prop] = Object.assign({}, this.originalCopy[prop]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//force reset
|
// force reset
|
||||||
this.retrieveConfig();
|
this.retrieveConfig();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -508,4 +504,4 @@ export class ConfigurationComponent implements OnInit, OnDestroy {
|
|||||||
disabled(prop: any): boolean {
|
disabled(prop: any): boolean {
|
||||||
return !(prop && prop.editable);
|
return !(prop && prop.editable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,7 @@ export class InlineAlertComponent {
|
|||||||
blinking: boolean = false;
|
blinking: boolean = false;
|
||||||
|
|
||||||
@Output() confirmEvt = new EventEmitter<boolean>();
|
@Output() confirmEvt = new EventEmitter<boolean>();
|
||||||
|
@Output() closeEvt = new EventEmitter<boolean>();
|
||||||
|
|
||||||
constructor(private translate: TranslateService) { }
|
constructor(private translate: TranslateService) { }
|
||||||
|
|
||||||
@ -82,9 +83,10 @@ export class InlineAlertComponent {
|
|||||||
this.useAppLevelStyle = false;
|
this.useAppLevelStyle = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Close alert
|
// Close alert
|
||||||
public close(): void {
|
public close(): void {
|
||||||
this.alertClose = true;
|
this.alertClose = true;
|
||||||
|
this.closeEvt.emit(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public blink() {
|
public blink() {
|
||||||
|
@ -9,18 +9,15 @@
|
|||||||
"check-space"
|
"check-space"
|
||||||
],
|
],
|
||||||
"curly": true,
|
"curly": true,
|
||||||
"eofline": true,
|
"eofline": false,
|
||||||
"forin": true,
|
"forin": false,
|
||||||
"indent": [
|
"indent": [
|
||||||
true,
|
true,
|
||||||
"spaces"
|
"spaces"
|
||||||
],
|
],
|
||||||
"label-position": true,
|
"label-position": true,
|
||||||
"label-undefined": true,
|
"label-undefined": true,
|
||||||
"max-line-length": [
|
"max-line-length": false,
|
||||||
false,
|
|
||||||
140
|
|
||||||
],
|
|
||||||
"member-access": false,
|
"member-access": false,
|
||||||
"member-ordering": [
|
"member-ordering": [
|
||||||
true,
|
true,
|
||||||
@ -74,7 +71,8 @@
|
|||||||
],
|
],
|
||||||
"quotemark": [
|
"quotemark": [
|
||||||
true,
|
true,
|
||||||
"single"
|
"double",
|
||||||
|
"avoid-escape"
|
||||||
],
|
],
|
||||||
"radix": true,
|
"radix": true,
|
||||||
"semicolon": [
|
"semicolon": [
|
||||||
|
Loading…
Reference in New Issue
Block a user