Compare commits

...

22 Commits

Author SHA1 Message Date
Bai
a048edf24f fix: approve ticket special account not found 2024-12-18 16:06:34 +08:00
wangruidong
a9ba931bba perf: Add 'labels' column to AssetPermission and Domain tables 2024-12-18 10:55:48 +08:00
wangruidong
23fae59411 feat: Add permission checks for platform editing 2024-12-17 19:10:27 +08:00
Chenyang Shen
320613d15d Merge pull request #4520 from jumpserver/pr@dev@feat_add_translate
feat: add translate
2024-12-17 17:42:07 +08:00
Aaron3S
57ea32e785 feat: add translate 2024-12-17 17:40:44 +08:00
Eric
3e3f80c59b perf: component names use the same letter case 2024-12-17 16:21:31 +08:00
feng
c15ba5b078 fix: tag search display error 2024-12-17 10:32:18 +08:00
wangruidong
651888faab perf: Add 'labels' column to UserGroupList table 2024-12-16 19:00:00 +08:00
feng626
d220047fe2 Revert "perf: Platform global"
This reverts commit bbe80f0292.
2024-12-16 14:09:49 +08:00
feng
bbe80f0292 perf: Platform global 2024-12-16 11:40:35 +08:00
feng
41e73a2c9b perf: Firefox unable to download file 2024-12-13 12:51:52 +08:00
feng
7d89cf9f45 perf: Re-login after csrf expires 2024-12-13 10:23:36 +08:00
Bai
8a048f692f fix: remove log 2024-12-12 18:49:39 +08:00
Bai
800317346c fix: current org is system and no preorg user logout error 2024-12-12 11:35:31 +08:00
wangruidong
4a1e2db7ca fix: Org admin view platform perms 2024-12-11 19:12:57 +08:00
Bai
6702d94ba1 fix: org changed error 2024-12-11 10:37:56 +08:00
Bai
a87d04fb9d fix: user login always change to system org 2024-12-10 19:14:13 +08:00
zhaojisen
367db0daf1 fixed: Fixed a text wrap issue 2024-12-10 16:05:55 +08:00
zhaojisen
583b28a6c4 fixed: Fixed an organization error after entering Settings under Global Organization manually 2024-12-09 17:19:37 +08:00
Chenyang Shen
ec5f2e69eb Merge pull request #4498 from jumpserver/pr@dev@feat_change_face_context_url
feat: change face context url
2024-12-09 16:55:22 +08:00
Aaron3S
d058f0e777 feat: change face context url 2024-12-09 16:53:52 +08:00
老广
89befaad43 Create llm-code-review.yml 2024-12-09 16:20:12 +08:00
21 changed files with 123 additions and 52 deletions

View File

@@ -0,0 +1,28 @@
name: LLM Code Review
permissions:
contents: read
pull-requests: write
on:
pull_request:
types: [opened, reopened, synchronize]
jobs:
llm-code-review:
runs-on: ubuntu-latest
steps:
- uses: fit2cloud/LLM-CodeReview-Action@main
env:
GITHUB_TOKEN: ${{ secrets.FIT2CLOUDRD_LLM_CODE_REVIEW_TOKEN }}
OPENAI_API_KEY: ${{ secrets.ALIYUN_LLM_API_KEY }}
LANGUAGE: English
OPENAI_API_ENDPOINT: https://dashscope.aliyuncs.com/compatible-mode/v1
MODEL: qwen2-1.5b-instruct
PROMPT: "Please check the following code differences for any irregularities, potential issues, or optimization suggestions, and provide your answers in English."
top_p: 1
temperature: 1
# max_tokens: 10000
MAX_PATCH_LENGTH: 10000
IGNORE_PATTERNS: "/node_modules,*.md,/dist,/.github"
FILE_PATTERNS: "*.java,*.go,*.py,*.vue,*.ts,*.js,*.css,*.scss,*.html"

View File

@@ -225,7 +225,7 @@ export default {
})
},
startFaceCapture() {
const url = '/api/v1/authentication/mfa/face/context/'
const url = '/api/v1/authentication/face/context/'
this.$axios.post(url).then(data => {
const token = data['token']
this.faceCaptureUrl = '/facelive/capture?token=' + token

View File

@@ -78,7 +78,7 @@ export default {
formatterData = data
}
return (
<span style={{ whiteSpace: 'pre-wrap', lineHeight: '1.2' }}>{formatterData}</span>
<span style={{ whiteSpace: 'pre-wrap', wordBreak: 'break-word', lineHeight: '1.2' }}>{formatterData}</span>
)
}
if (this.value instanceof Array) {

View File

@@ -202,9 +202,10 @@ export default {
label: current.label,
value: valueDecode
}
if (curChildren.length > 0) {
for (const item of curChildren) {
if (valueDecode === item.value) {
if (valueDecode === String(item.value)) {
searchFieldOption.valueLabel = item.label
break
}

View File

@@ -71,7 +71,7 @@ export default {
},
async logout() {
const currentOrg = this.$store.getters.currentOrg
if (currentOrg.autoEnter) {
if (currentOrg.autoEnter || currentOrg.is_system) {
await this.$store.dispatch('users/setCurrentOrg', this.$store.getters.preOrg)
}
window.location.href = `${process.env.VUE_APP_LOGOUT_PATH}?next=${this.$route.fullPath}`

View File

@@ -2,7 +2,6 @@ import i18n from '@/i18n/i18n'
import empty from '@/layout/empty'
import XPackRoutes from './xpack'
const globalSubmenu = () => import('@/layout/globalOrg.vue')
export default [
{
path: 'assets',
@@ -294,12 +293,11 @@ export default [
},
{
path: 'platforms',
component: globalSubmenu,
component: empty,
meta: {
permissions: ['assets.view_platform'],
resource: 'platform',
icon: 'platform',
disableOrgsChange: true
icon: 'platform'
},
redirect: '',
children: [

View File

@@ -71,10 +71,11 @@ const mutations = {
state.consoleOrgs = state.consoleOrgs.filter(i => i.id !== org.id)
},
SET_CURRENT_ORG(state, org) {
// 系统组织和全局组织不设置成 Pre org
if (!state.currentOrg?.autoEnter && !state.currentOrg?.is_root) {
state.preOrg = state.currentOrg
setPreOrgLocal(state.username, state.currentOrg)
// 系统组织不设置成 Pre org
const currentOrg = state.currentOrg
if (currentOrg && !currentOrg.autoEnter && !currentOrg.is_system) {
state.preOrg = currentOrg
setPreOrgLocal(state.username, currentOrg)
}
state.currentOrg = org
saveCurrentOrgLocal(state.username, org)
@@ -144,6 +145,7 @@ const actions = {
const systemOrg = {
id: orgUtil.SYSTEM_ORG_ID,
name: 'SystemSetting',
is_system: true,
autoEnter: new Date().getTime()
}
commit('SET_CURRENT_ORG', systemOrg)

View File

@@ -42,8 +42,13 @@ export function getCurrentOrgLocal(username) {
export function saveCurrentOrgLocal(username, org) {
const key = CURRENT_ORG_KEY + ':' + username
localStorage.setItem(key, JSON.stringify(org))
VueCookie.set('X-JMS-ORG', org.id)
if (org) {
localStorage.setItem(key, JSON.stringify(org))
VueCookie.set('X-JMS-ORG', org.id)
} else {
localStorage.removeItem(key)
VueCookie.delete('X-JMS-ORG')
}
}
export function setPreOrgLocal(username, org) {

View File

@@ -222,16 +222,32 @@ export function download(downloadUrl, filename) {
const iframe = document.createElement('iframe')
iframe.style.display = 'none'
document.body.appendChild(iframe)
const a = document.createElement('a')
a.href = downloadUrl
const timeout = 1000 * 60 * 30
if (filename) {
a.download = filename
fetch(downloadUrl)
.then(response => response.blob())
.then(blob => {
const url = URL.createObjectURL(blob)
const a = iframe.contentWindow.document.createElement('a')
a.href = url
a.download = filename
iframe.contentWindow.document.body.appendChild(a)
a.click()
setTimeout(() => {
URL.revokeObjectURL(url)
document.body.removeChild(iframe)
}, timeout) // If you can't download it in half an hour, don't download it.
})
.catch(() => {
document.body.removeChild(iframe)
})
} else {
iframe.src = downloadUrl
setTimeout(() => {
document.body.removeChild(iframe)
}, timeout) // If you can't download it in half an hour, don't download it.
}
iframe.contentWindow.document.body.appendChild(a)
a.click()
setTimeout(() => {
document.body.removeChild(iframe)
}, 1000 * 60 * 30) // If you can't download it in half an hour, don't download it.
}
export function diffObject(object, base) {

View File

@@ -17,7 +17,7 @@ function getPropOrg() {
if (defaultOrg) {
return defaultOrg
}
return orgs.filter(item => !item['is_root'] && item.id !== SYSTEM_ORG_ID)[0]
return orgs.filter(item => !item['is_root'] && !item['is_system'])[0]
}
async function change2PropOrg() {

View File

@@ -89,10 +89,18 @@ function ifBadRequest({ response, error }) {
}
}
export function logout() {
window.location.href = `${process.env.VUE_APP_LOGOUT_PATH}?next=${router.fullPath}`
}
export function flashErrorMsg({ response, error }) {
if (!response.config.disableFlashErrorMsg) {
const responseErrorMsg = getErrorResponseMsg(error)
const msg = responseErrorMsg || error.message
if (response.status === 403 && msg === 'CSRF Failed: CSRF token missing.') {
setTimeout(() => { logout() }, 1000)
}
message({
message: msg,
type: 'error',

View File

@@ -8,7 +8,10 @@ import orgs from '@/api/orgs'
import { getPropView, isViewHasOrgs } from '@/utils/jms'
const whiteList = ['/login', process.env.VUE_APP_LOGIN_PATH] // no redirect whitelist
const autoEnterOrgs = ['00000000-0000-0000-0000-000000000001', '00000000-0000-0000-0000-000000000000']
const autoEnterOrgs = [
'00000000-0000-0000-0000-000000000001',
'00000000-0000-0000-0000-000000000000'
]
function reject(msg) {
return new Promise((resolve, reject) => reject(msg))
@@ -170,19 +173,24 @@ export async function startup({ to, from, next }) {
if (store.getters.inited) {
return true
}
await store.dispatch('app/init')
// set page title
// await getOpenPublicSetting({ to, from, next })
await getPublicSetting({ to, from, next }, true)
await checkLogin({ to, from, next })
await onI18nLoaded()
await getPublicSetting({ to, from, next }, false)
await changeCurrentViewIfNeed({ to, from, next })
await changeCurrentOrgIfNeed({ to, from, next })
await generatePageRoutes({ to, from, next })
await checkUserFirstLogin({ to, from, next })
await store.dispatch('assets/getAssetCategories')
try {
await store.dispatch('app/init')
// set page title
// await getOpenPublicSetting({ to, from, next })
await getPublicSetting({ to, from, next }, true)
await checkLogin({ to, from, next })
await onI18nLoaded()
await getPublicSetting({ to, from, next }, false)
await changeCurrentViewIfNeed({ to, from, next })
await changeCurrentOrgIfNeed({ to, from, next })
await generatePageRoutes({ to, from, next })
await checkUserFirstLogin({ to, from, next })
await store.dispatch('assets/getAssetCategories')
} catch (e) {
Vue.$log.error('Startup error: ', e)
}
return true
}

View File

@@ -16,7 +16,7 @@ export default {
url: '/api/v1/assets/domains/',
columnsExclude: ['gateway'],
columnsExtra: ['gateways'],
columns: ['name', 'assets_amount', 'gateways', 'comment', 'actions'],
columns: ['name', 'assets_amount', 'gateways', 'labels', 'comment', 'actions'],
columnsShow: {
min: ['name', 'actions'],
default: ['name', 'assets_amount', 'gateways', 'comment', 'actions']

View File

@@ -122,7 +122,7 @@ export default {
},
onCanSetting() {
const filterField = Object.keys(this.remoteMeta)
this.canSetting = filterField.includes(this.method)
this.canSetting = filterField.includes(this.method) && this.$hasPerm('assets.change_platform')
this.$emit('canSetting', this.canSetting)
return this.canSetting
},

View File

@@ -27,6 +27,7 @@ export default {
}
},
data() {
const canEdit = !this.object['internal'] && this.$hasPerm('assets.change_platform')
return {
loading: true,
initial: {
@@ -35,14 +36,14 @@ export default {
}
},
url: `/api/v1/assets/platforms/`,
disabled: this.object.internal,
disabled: !canEdit,
hasReset: false,
hasDetailInMsg: false,
submitMethod: () => 'patch',
fields: [['', ['automation']]],
fieldsMeta: platformFieldsMeta(this),
onSubmit: this.submit,
canSubmit: !this.object.internal,
canSubmit: canEdit,
defaultOptions: {},
afterGetFormValue: (obj) => {
updateAutomationParams(this, obj)
@@ -65,7 +66,7 @@ export default {
},
methods: {
submit(validValues) {
if (!this.$hasPerm('assets.change_platform') || !this.isSystemAdmin) {
if (!this.canSubmit || !this.isSystemAdmin) {
return this.$message.error(this.$tc('NoPermission'))
}
this.$axios.patch(`${this.url}${this.object.id}/`, validValues).then(() => {

View File

@@ -10,10 +10,10 @@
v-if="protocolChoices"
v-model="object.protocols"
:choices="protocolChoices"
:readonly="object['internal']"
:readonly="!canEdit"
/>
<el-button
v-if="!object.internal"
v-if="canEdit"
size="small"
style="margin-top: 10px"
type="primary"
@@ -71,7 +71,8 @@ export default {
],
protocolChoices: null,
constraints: {}
constraints: {},
canEdit: !this.object['internal'] && this.$hasPerm('assets.change_platform')
}
},
computed: {},
@@ -103,7 +104,7 @@ export default {
attrs: {
label: this.$t('Update'),
model: object['domain_enabled'],
disabled: object['internal'] || this.constraints['domain_enabled'] === false
disabled: !this.canEdit || this.constraints['domain_enabled'] === false
},
callbacks: Object.freeze({
change: (val) => {
@@ -120,7 +121,7 @@ export default {
type: 'switch',
attrs: {
model: object['su_enabled'],
disabled: object['internal'] || this.constraints['su_enabled'] === false
disabled: !this.canEdit || this.constraints['su_enabled'] === false
},
callbacks: Object.freeze({
change: (val) => {
@@ -136,7 +137,8 @@ export default {
title: this.$t('SyncProtocolToAsset'),
attrs: {
type: 'primary',
label: this.$t('Sync')
label: this.$t('Sync'),
disabled: !this.canEdit
},
callbacks: Object.freeze({
click: () => {

View File

@@ -50,7 +50,7 @@ export default {
columnsExtra: ['action'],
columns: [
'name', 'users_amount', 'user_groups_amount', 'assets_amount', 'nodes_amount',
'accounts', 'is_valid', 'is_expired', 'from_ticket', 'is_active', 'actions'
'accounts', 'labels', 'is_valid', 'is_expired', 'from_ticket', 'is_active', 'actions'
],
columnsShow: {
min: ['name', 'actions'],

View File

@@ -84,7 +84,7 @@ export default {
currentEdit: '',
biometricFeaturesActions: [
{
title: this.$t('Face'),
title: this.$t('FacialFeatures'),
attrs: {
type: 'primary',
label: this.$store.state.users.profile.is_face_code_set ? this.$t('Unbind') : this.$t('Bind')

View File

@@ -90,7 +90,7 @@ export default {
omnidb: 'OmniDB',
guacamole: 'Guacamole',
lion: 'Lion',
xrdp: 'XRDP',
xrdp: 'Xrdp',
razor: 'Razor',
core: 'Core',
celery: 'Celery',
@@ -100,7 +100,7 @@ export default {
kael: 'Kael',
video_worker: 'Video-Worker',
panda: 'Panda',
nec: 'NEC',
nec: 'Nec',
facelive: 'Facelive'
}
return nameMapper[this.componentMetric.type]

View File

@@ -24,6 +24,7 @@
v-model="requestForm.accounts"
:assets="requestForm.assets"
:nodes="requestForm.nodes"
:oid="requestForm.oid"
:show-add-template="false"
style="width: 50% !important"
/>
@@ -82,6 +83,7 @@ export default {
assets: this.object.apply_assets?.map(i => i.id),
accounts: this.object.apply_accounts,
actions: this.object.apply_actions,
oid: this.object.org_id,
apply_date_expired: this.object.apply_date_expired,
apply_date_start: this.object.apply_date_start
},

View File

@@ -14,7 +14,7 @@ export default {
return {
tableConfig: {
url: '/api/v1/users/groups/',
columns: ['name', 'users_amount', 'comment', 'actions'],
columns: ['name', 'users_amount', 'comment', 'actions', 'labels'],
columnsShow: {
default: ['name', 'users_amount', 'comment', 'actions'],
min: ['name', 'action']