Compare commits

...

7 Commits
main ... v1.8.1

Author SHA1 Message Date
github-actions[bot] d3710a66ca
[Backport release-1.8] Fix: User can't be updated (#806)
* Fix: User can't be updated

Signed-off-by: barnettZQG <barnett.zqg@gmail.com>
(cherry picked from commit 5917812775)

* Fix: Remove the unuseful code

Signed-off-by: barnettZQG <barnett.zqg@gmail.com>
(cherry picked from commit 75a9ddaebc)

---------

Co-authored-by: barnettZQG <barnett.zqg@gmail.com>
2023-04-28 11:58:11 +08:00
github-actions[bot] cedb5774bc
Fix: Check the permission before request the compare API (#805)
Signed-off-by: barnettZQG <barnett.zqg@gmail.com>
(cherry picked from commit 778901f946)

Co-authored-by: barnettZQG <barnett.zqg@gmail.com>
2023-04-28 11:57:59 +08:00
github-actions[bot] 74695e5d4f
Fix: Show policy type when editing the policy (#804)
Signed-off-by: barnettZQG <barnett.zqg@gmail.com>
(cherry picked from commit c3d817f6dc)

Co-authored-by: barnettZQG <barnett.zqg@gmail.com>
2023-04-28 11:57:47 +08:00
github-actions[bot] 108069563d
[Backport release-1.8] Fix: Application Graph displays exception stack trace (#801)
* Application Graph displays exception stack trace

Signed-off-by: liyanfang <liyanfang@cmss.chinamobile.com>
(cherry picked from commit 95b182e59f)

* Fix: Application Graph displays exception stack trace

Signed-off-by: liyanfang <liyanfang@cmss.chinamobile.com>
(cherry picked from commit 67b0e38e8d)

---------

Co-authored-by: liyanfang <liyanfang@cmss.chinamobile.com>
2023-04-28 10:09:07 +08:00
github-actions[bot] b959214ca7
Fix: Modifying Memory Units (#794)
Signed-off-by: jiaxiaolei <584736476@qq.com>
(cherry picked from commit 3c1dd6b378)

Co-authored-by: jiaxiaolei <584736476@qq.com>
2023-04-27 10:09:46 +08:00
github-actions[bot] a61257617a
Fix: Remove the label confluct checking (#789)
Signed-off-by: barnettZQG <barnett.zqg@gmail.com>
(cherry picked from commit ed1eb1123e)

Co-authored-by: barnettZQG <barnett.zqg@gmail.com>
2023-04-24 17:28:07 +08:00
github-actions[bot] d342b28cd0
Fix: The sub length of the dex user more than 31 (#788)
Signed-off-by: barnettZQG <barnett.zqg@gmail.com>
(cherry picked from commit 00e3717021)

Co-authored-by: barnettZQG <barnett.zqg@gmail.com>
2023-04-24 17:27:52 +08:00
13 changed files with 51 additions and 34 deletions

View File

@ -165,7 +165,6 @@ export const ComponentNode = (props: ComponentNodeProps) => {
</Balloon> </Balloon>
); );
}; };
const graphNode = ( const graphNode = (
<div <div
className={classNames('graph-node', 'graph-node-resource', { className={classNames('graph-node', 'graph-node-resource', {
@ -203,7 +202,7 @@ export const ComponentNode = (props: ComponentNodeProps) => {
<If condition={traits.length > 0}> <If condition={traits.length > 0}>
<div className={classNames('label-traits')}> <div className={classNames('label-traits')}>
{traits && ( {traits && traits.length > 0 && traits[0] && (
<Tag animation={true}> <Tag animation={true}>
<span <span
className={classNames('circle', { className={classNames('circle', {

View File

@ -34,7 +34,7 @@ class MemoryNumber extends React.Component<Props, State> {
id={id} id={id}
min="0" min="0"
disabled={disabled} disabled={disabled}
addonTextAfter="MB" addonTextAfter="Mi"
htmlType="number" htmlType="number"
onChange={this.onChange} onChange={this.onChange}
value={initValue && initValue} value={initValue && initValue}

View File

@ -51,6 +51,8 @@
"Policies": "策略", "Policies": "策略",
"Policy": "策略", "Policy": "策略",
"New Policy": "新增策略", "New Policy": "新增策略",
"Policy Type": "策略类型",
"Update Policy": "编辑策略",
"Warning": "部署异常", "Warning": "部署异常",
"EnvironmentPlan": "环境规划", "EnvironmentPlan": "环境规划",
"BasisConfig": "基准配置", "BasisConfig": "基准配置",

View File

@ -467,7 +467,8 @@ class PolicyDialog extends React.Component<Props, State> {
this.uiSchemaRef.current?.validate(callback); this.uiSchemaRef.current?.validate(callback);
}; };
const init = this.field.init; const init = this.field.init;
const span = selectedPolicyItem && selectedPolicyItem?.name == 'custom' ? 8 : 12; const showType = (selectedPolicyItem && selectedPolicyItem?.name == 'custom') || policy != undefined;
const span = showType ? 8 : 12;
return ( return (
<DrawerWithFooter <DrawerWithFooter
title={policy ? i18n.t('Update Policy') : i18n.t('New Policy')} title={policy ? i18n.t('Update Policy') : i18n.t('New Policy')}
@ -478,7 +479,7 @@ class PolicyDialog extends React.Component<Props, State> {
> >
<Form field={this.field}> <Form field={this.field}>
<Card contentHeight="auto" title={i18n.t('Select a policy type').toString()}> <Card contentHeight="auto" title={i18n.t('Select a policy type').toString()}>
<If condition={!policy}> {!policy && (
<Row wrap={true}> <Row wrap={true}>
{items.map((item) => { {items.map((item) => {
return ( return (
@ -496,12 +497,12 @@ class PolicyDialog extends React.Component<Props, State> {
); );
})} })}
</Row> </Row>
</If> )}
<If condition={selectedPolicyItem}> {selectedPolicyItem && (
<Row wrap={true}> <Row wrap={true}>
{selectedPolicyItem && selectedPolicyItem?.name == 'custom' && ( {showType && (
<Col span={span} style={{ padding: '0 8px' }}> <Col span={span} style={{ padding: '0 8px' }}>
<Form.Item label="Policy Type" required> <Form.Item label={i18n.t('Policy Type')} required>
<Select <Select
{...init('type', { {...init('type', {
rules: [ rules: [
@ -569,7 +570,7 @@ class PolicyDialog extends React.Component<Props, State> {
</Form.Item> </Form.Item>
</Col> </Col>
</Row> </Row>
</If> )}
<If condition={selectedPolicyItem?.properties}> <If condition={selectedPolicyItem?.properties}>
<Message style={{ marginTop: '8px' }} type="success"> <Message style={{ marginTop: '8px' }} type="success">
<Translation>This policy already have the default properties</Translation> <Translation>This policy already have the default properties</Translation>

View File

@ -27,6 +27,8 @@ import type { Endpoint } from '../../../../interface/observation';
import type { Target } from '../../../../interface/target'; import type { Target } from '../../../../interface/target';
import { locale } from '../../../../utils/locale'; import { locale } from '../../../../utils/locale';
import { getLink } from '../../../../utils/utils'; import { getLink } from '../../../../utils/utils';
import { checkPermission } from '../../../../utils/permission';
import { LoginUserInfo } from '../../../../interface/user';
export type GatewayIP = { export type GatewayIP = {
ip: string; ip: string;
@ -47,6 +49,7 @@ type Props = {
disableStatusShow?: boolean; disableStatusShow?: boolean;
refresh: () => void; refresh: () => void;
dispatch: ({}) => void; dispatch: ({}) => void;
userInfo?: LoginUserInfo;
}; };
type State = { type State = {
@ -162,11 +165,23 @@ class Header extends Component<Props, State> {
}; };
compareCurrentWithCluster = (appName: string, envName: string) => { compareCurrentWithCluster = (appName: string, envName: string) => {
const { applicationStatus } = this.props; const { applicationStatus, applicationDetail, userInfo } = this.props;
if (!applicationStatus) { if (!applicationStatus) {
this.setState({ compare: undefined }); this.setState({ compare: undefined });
return; return;
} }
if (
!checkPermission(
{
resource: `project:${applicationDetail?.project?.name}/application:${applicationDetail?.name}`,
action: 'compare',
},
applicationDetail?.project?.name,
userInfo
)
) {
return;
}
compareApplication(appName, { compareLatestWithRunning: { env: envName } }).then( compareApplication(appName, { compareLatestWithRunning: { env: envName } }).then(
(res: ApplicationCompareResponse) => { (res: ApplicationCompareResponse) => {
this.setState({ compare: res }); this.setState({ compare: res });

View File

@ -466,6 +466,7 @@ class ApplicationInstanceList extends React.Component<Props, State> {
<div> <div>
<Header <Header
envbinding={envbinding} envbinding={envbinding}
userInfo={userInfo}
targets={this.getTargets()} targets={this.getTargets()}
components={components} components={components}
envName={envName} envName={envName}

View File

@ -306,6 +306,7 @@ class ApplicationStatusPage extends React.Component<Props, State> {
<div className="application-status-wrapper"> <div className="application-status-wrapper">
<Loading visible={loading && endpointLoading} style={{ width: '100%' }}> <Loading visible={loading && endpointLoading} style={{ width: '100%' }}>
<Header <Header
userInfo={userInfo}
envbinding={this.getEnvbindingByName()} envbinding={this.getEnvbindingByName()}
targets={this.getTargets()} targets={this.getTargets()}
envName={envName} envName={envName}

View File

@ -24,6 +24,7 @@ import { beautifyTime } from '../../utils/common';
import { locale } from '../../utils/locale'; import { locale } from '../../utils/locale';
import ApplicationWorkflowRecord from './components/WorkflowRecord'; import ApplicationWorkflowRecord from './components/WorkflowRecord';
import { LoginUserInfo } from '../../interface/user';
const { Row, Col } = Grid; const { Row, Col } = Grid;
@ -34,6 +35,7 @@ type Props = {
applicationStatus?: ApplicationStatus; applicationStatus?: ApplicationStatus;
envbinding: EnvBinding[]; envbinding: EnvBinding[];
workflows: Workflow[]; workflows: Workflow[];
userInfo?: LoginUserInfo;
}; };
type State = { type State = {
@ -49,7 +51,7 @@ type State = {
}; };
@connect((store: any) => { @connect((store: any) => {
return { ...store.application }; return { ...store.application, ...store.user };
}) })
class ApplicationWorkflow extends React.Component<Props, State> { class ApplicationWorkflow extends React.Component<Props, State> {
constructor(props: Props) { constructor(props: Props) {
@ -136,7 +138,7 @@ class ApplicationWorkflow extends React.Component<Props, State> {
runApplicationWorkflow = () => {}; runApplicationWorkflow = () => {};
render() { render() {
const { applicationDetail, dispatch, applicationStatus, workflows } = this.props; const { applicationDetail, dispatch, applicationStatus, workflows, userInfo } = this.props;
const { const {
params: { record, appName, envName }, params: { record, appName, envName },
} = this.props.match; } = this.props.match;
@ -177,6 +179,7 @@ class ApplicationWorkflow extends React.Component<Props, State> {
return ( return (
<div className="run-layout"> <div className="run-layout">
<Header <Header
userInfo={userInfo}
envbinding={this.getEnvbindingByName()} envbinding={this.getEnvbindingByName()}
envName={envName} envName={envName}
appName={appName} appName={appName}

View File

@ -3,7 +3,6 @@ import React from 'react';
import { createUser, updateUser } from '../../../../api/users'; import { createUser, updateUser } from '../../../../api/users';
import DrawerWithFooter from '../../../../components/Drawer'; import DrawerWithFooter from '../../../../components/Drawer';
import { If } from '../../../../components/If';
import { Translation } from '../../../../components/Translation'; import { Translation } from '../../../../components/Translation';
import i18n from '../../../../i18n'; import i18n from '../../../../i18n';
import type { RolesBase } from '../../../../interface/roles'; import type { RolesBase } from '../../../../interface/roles';
@ -196,7 +195,7 @@ class CreateUser extends React.Component<Props, State> {
</Col> </Col>
</Row> </Row>
<Row> <Row>
<If condition={!isEditUser}> {!isEditUser && (
<Col span={12} style={{ padding: '0 8px' }}> <Col span={12} style={{ padding: '0 8px' }}>
<FormItem label={<Translation>Password</Translation>} required> <FormItem label={<Translation>Password</Translation>} required>
<Input <Input
@ -220,7 +219,7 @@ class CreateUser extends React.Component<Props, State> {
/> />
</FormItem> </FormItem>
</Col> </Col>
</If> )}
<Col span={12} style={{ padding: '0 8px' }}> <Col span={12} style={{ padding: '0 8px' }}>
<FormItem label={<Translation>Email</Translation>} required> <FormItem label={<Translation>Email</Translation>} required>
<Input <Input

View File

@ -26,7 +26,6 @@ import (
"github.com/oam-dev/kubevela/pkg/multicluster" "github.com/oam-dev/kubevela/pkg/multicluster"
"github.com/oam-dev/kubevela/pkg/oam" "github.com/oam-dev/kubevela/pkg/oam"
"github.com/oam-dev/kubevela/pkg/utils" "github.com/oam-dev/kubevela/pkg/utils"
velaerr "github.com/oam-dev/kubevela/pkg/utils/errors"
"github.com/kubevela/velaux/pkg/server/domain/model" "github.com/kubevela/velaux/pkg/server/domain/model"
"github.com/kubevela/velaux/pkg/server/infrastructure/datastore" "github.com/kubevela/velaux/pkg/server/infrastructure/datastore"
@ -38,28 +37,15 @@ func CreateTargetNamespace(ctx context.Context, k8sClient client.Client, cluster
if clusterName == "" || namespace == "" { if clusterName == "" || namespace == "" {
return bcode.ErrTargetInvalidWithEmptyClusterOrNamespace return bcode.ErrTargetInvalidWithEmptyClusterOrNamespace
} }
err := utils.CreateOrUpdateNamespace(multicluster.ContextWithClusterName(ctx, clusterName), k8sClient, namespace, utils.MergeOverrideLabels(map[string]string{ return utils.CreateOrUpdateNamespace(multicluster.ContextWithClusterName(ctx, clusterName), k8sClient, namespace, utils.MergeOverrideLabels(map[string]string{
oam.LabelRuntimeNamespaceUsage: oam.VelaNamespaceUsageTarget, oam.LabelRuntimeNamespaceUsage: oam.VelaNamespaceUsageTarget,
}), utils.MergeNoConflictLabels(map[string]string{
oam.LabelNamespaceOfTargetName: targetName, oam.LabelNamespaceOfTargetName: targetName,
})) }))
if velaerr.IsLabelConflict(err) {
klog.Errorf("update namespace for target err %v", err)
return bcode.ErrTargetNamespaceAlreadyBound
}
if err != nil {
return err
}
return nil
} }
// DeleteTargetNamespace delete the namespace of the target // DeleteTargetNamespace delete the namespace of the target
func DeleteTargetNamespace(ctx context.Context, k8sClient client.Client, clusterName, namespace, targetName string) error { func DeleteTargetNamespace(ctx context.Context, k8sClient client.Client, clusterName, namespace, targetName string) error {
err := utils.UpdateNamespace(multicluster.ContextWithClusterName(ctx, clusterName), k8sClient, namespace, err := utils.UpdateNamespace(multicluster.ContextWithClusterName(ctx, clusterName), k8sClient, namespace,
// check no conflict label first to make sure the namespace belong to the target, then override it
utils.MergeNoConflictLabels(map[string]string{
oam.LabelNamespaceOfTargetName: targetName,
}),
utils.MergeOverrideLabels(map[string]string{ utils.MergeOverrideLabels(map[string]string{
oam.LabelRuntimeNamespaceUsage: "", oam.LabelRuntimeNamespaceUsage: "",
oam.LabelNamespaceOfTargetName: "", oam.LabelNamespaceOfTargetName: "",

View File

@ -492,8 +492,14 @@ func (d *dexHandlerImpl) login(ctx context.Context) (*apisv1.UserBase, error) {
klog.Errorf("failed to get the system info %s", err.Error()) klog.Errorf("failed to get the system info %s", err.Error())
} }
user := &model.User{ user := &model.User{
Email: claims.Email, Email: claims.Email,
Name: strings.ToLower(claims.Sub), Name: func() string {
sub := strings.ToLower(claims.Sub)
if len(sub) > datastore.PrimaryKeyMaxLength {
return sub[:datastore.PrimaryKeyMaxLength]
}
return sub
}(),
DexSub: claims.Sub, DexSub: claims.Sub,
Alias: claims.Name, Alias: claims.Name,
LastLoginTime: time.Now(), LastLoginTime: time.Now(),

View File

@ -46,6 +46,9 @@ var (
ErrEntityInvalid = NewDBError(fmt.Errorf("entity is invalid")) ErrEntityInvalid = NewDBError(fmt.Errorf("entity is invalid"))
) )
// PrimaryKeyMaxLength The primary key length should be limited when the datastore is kube-api
var PrimaryKeyMaxLength = 31
// DBError datastore error // DBError datastore error
type DBError struct { type DBError struct {
err error err error

View File

@ -23,6 +23,7 @@ import (
"github.com/go-playground/validator/v10" "github.com/go-playground/validator/v10"
"github.com/kubevela/velaux/pkg/server/domain/service" "github.com/kubevela/velaux/pkg/server/domain/service"
"github.com/kubevela/velaux/pkg/server/infrastructure/datastore"
) )
var validate = validator.New() var validate = validator.New()
@ -72,7 +73,7 @@ func ValidatePayloadType(fl validator.FieldLevel) bool {
// ValidateName custom check name field // ValidateName custom check name field
func ValidateName(fl validator.FieldLevel) bool { func ValidateName(fl validator.FieldLevel) bool {
value := fl.Field().String() value := fl.Field().String()
if len(value) > 31 || len(value) < 2 { if len(value) > datastore.PrimaryKeyMaxLength || len(value) < 2 {
return false return false
} }
return nameRegexp.MatchString(value) return nameRegexp.MatchString(value)