Skip to content

Commit debaf13

Browse files
committed
Fixed permissions issue and modpack issue with environment overhaul
1 parent 697468e commit debaf13

File tree

9 files changed

+94
-26
lines changed

9 files changed

+94
-26
lines changed

apps/frontend/src/pages/[type]/[id].vue

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -764,7 +764,16 @@
764764
>
765765
{{ formatMessage(messages.environmentMigrationMessage) }}
766766
<ButtonStyled color="orange">
767-
<nuxt-link :to="`/project/${project.id}/settings/environment`" class="mt-3 w-fit">
767+
<nuxt-link
768+
v-tooltip="
769+
hasEditDetailsPermission
770+
? undefined
771+
: formatMessage(commonProjectSettingsMessages.noPermissionDescription)
772+
"
773+
:to="`/project/${project.id}/settings/environment`"
774+
class="mt-3 w-fit"
775+
:disabled="!hasEditDetailsPermission"
776+
>
768777
<SettingsIcon /> {{ formatMessage(messages.reviewEnvironmentSettings) }}
769778
</nuxt-link>
770779
</ButtonStyled>
@@ -957,6 +966,7 @@ import {
957966
ButtonStyled,
958967
Checkbox,
959968
commonMessages,
969+
commonProjectSettingsMessages,
960970
injectNotificationManager,
961971
NewModal,
962972
OverflowMenu,
@@ -1589,6 +1599,11 @@ const currentMember = computed(() => {
15891599
return val
15901600
})
15911601
1602+
const hasEditDetailsPermission = computed(() => {
1603+
const EDIT_DETAILS = 1 << 2
1604+
return (currentMember.value?.permissions & EDIT_DETAILS) === EDIT_DETAILS
1605+
})
1606+
15921607
versions.value = data.$computeVersions(versions.value, allMembers.value)
15931608
15941609
// Q: Why do this instead of computing the versions of featuredVersions?
@@ -1870,6 +1885,7 @@ provideProjectPageContext({
18701885
projectV2: project,
18711886
projectV3,
18721887
refreshProject: resetProject,
1888+
currentMember,
18731889
})
18741890
</script>
18751891

apps/frontend/src/pages/[type]/[id]/settings/environment.vue

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { defineMessages, useVIntl } from '@vintl/vintl'
1414
1515
const { formatMessage } = useVIntl()
1616
17-
const { projectV2, projectV3, refreshProject } = injectProjectPageContext()
17+
const { currentMember, projectV2, projectV3, refreshProject } = injectProjectPageContext()
1818
const { handleError } = injectNotificationManager()
1919
const api = injectApi()
2020
@@ -32,6 +32,11 @@ const needsToVerify = computed(
3232
supportsEnvironment.value,
3333
)
3434
35+
const hasPermission = computed(() => {
36+
const EDIT_DETAILS = 1 << 2
37+
return (currentMember.value?.permissions & EDIT_DETAILS) === EDIT_DETAILS
38+
})
39+
3540
function getInitialEnv() {
3641
return projectV3.value.environment?.length === 1 ? projectV3.value.environment[0] : undefined
3742
}
@@ -106,7 +111,7 @@ const messages = defineMessages({
106111
<template>
107112
<div>
108113
<UnsavedChangesPopup
109-
v-if="supportsEnvironment"
114+
v-if="supportsEnvironment && hasPermission"
110115
:original="saved"
111116
:modified="current"
112117
:saving="saving"
@@ -125,40 +130,43 @@ const messages = defineMessages({
125130
v-if="!supportsEnvironment"
126131
type="critical"
127132
:header="formatMessage(messages.wrongProjectTypeTitle)"
133+
:body="formatMessage(messages.wrongProjectTypeDescription)"
128134
class="mb-3"
129-
>
130-
{{ formatMessage(messages.wrongProjectTypeDescription) }}
131-
</Admonition>
135+
/>
132136
<template v-else>
133137
<Admonition
134-
v-if="
138+
v-if="!hasPermission"
139+
type="critical"
140+
:header="formatMessage(commonProjectSettingsMessages.noPermissionTitle)"
141+
:body="formatMessage(commonProjectSettingsMessages.noPermissionDescription)"
142+
class="mb-3"
143+
/>
144+
<Admonition
145+
v-else-if="
135146
!projectV3.environment ||
136147
projectV3.environment.length === 0 ||
137148
projectV3.environment[0] === 'unknown'
138149
"
139150
type="critical"
140151
:header="formatMessage(messages.missingEnvTitle)"
152+
:body="formatMessage(messages.missingEnvDescription)"
141153
class="mb-3"
142-
>
143-
{{ formatMessage(messages.missingEnvDescription) }}
144-
</Admonition>
154+
/>
145155
<Admonition
146156
v-else-if="projectV3.environment.length > 1"
147157
type="info"
148158
:header="formatMessage(messages.multipleEnvironmentsTitle)"
159+
:body="formatMessage(messages.multipleEnvironmentsDescription)"
149160
class="mb-3"
150-
>
151-
{{ formatMessage(messages.multipleEnvironmentsDescription) }}
152-
</Admonition>
161+
/>
153162
<Admonition
154163
v-else-if="needsToVerify"
155164
type="warning"
156165
:header="formatMessage(messages.reviewOptionsTitle)"
166+
:body="formatMessage(messages.reviewOptionsDescription)"
157167
class="mb-3"
158-
>
159-
{{ formatMessage(messages.reviewOptionsDescription) }}
160-
</Admonition>
161-
<ProjectSettingsEnvSelector v-model="current.environment" />
168+
/>
169+
<ProjectSettingsEnvSelector v-model="current.environment" :disabled="!hasPermission" />
162170
</template>
163171
</div>
164172
</div>

apps/frontend/src/pages/dashboard/projects.vue

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -456,9 +456,8 @@ if (user.value?.projects) {
456456
projects.value = updateSort(user.value.projects, 'Name', false)
457457
user.value?.projectsV3?.forEach((project) => {
458458
if (
459-
(project.side_types_migration_review_status === 'pending' &&
460-
project.project_types.includes('mod')) ||
461-
project.project_types.includes('modpack')
459+
project.side_types_migration_review_status === 'pending' &&
460+
(project.project_types.includes('mod') || project.project_types.includes('modpack'))
462461
) {
463462
projectsWithMigrationWarning.value.push(project.id)
464463
}

packages/ui/src/components/base/LargeRadioButton.vue

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
<template>
22
<button
3-
class="px-4 py-3 text-left border-0 font-medium border-2 border-button-bg border-solid flex gap-2 transition-all cursor-pointer active:scale-[0.98] hover:bg-button-bg hover:brightness-[--hover-brightness] rounded-xl"
4-
:class="selected ? 'text-contrast bg-button-bg' : 'text-primary bg-transparent'"
3+
class="px-4 py-3 text-left border-0 font-medium border-2 border-button-bg border-solid flex gap-2 transition-all cursor-pointer rounded-xl"
4+
:class="
5+
(selected ? 'text-contrast bg-button-bg' : 'text-primary bg-transparent') +
6+
(disabled
7+
? ' opacity-50'
8+
: ' active:scale-[0.98] hover:bg-button-bg hover:brightness-[--hover-brightness]')
9+
"
10+
:disabled="disabled"
511
@click="emit('select')"
612
>
713
<RadioButtonCheckedIcon v-if="selected" class="text-brand h-5 w-5 shrink-0" />
@@ -16,7 +22,13 @@ const emit = defineEmits<{
1622
(e: 'select'): void
1723
}>()
1824
19-
defineProps<{
20-
selected: boolean
21-
}>()
25+
withDefaults(
26+
defineProps<{
27+
selected: boolean
28+
disabled?: boolean
29+
}>(),
30+
{
31+
disabled: false,
32+
},
33+
)
2234
</script>

packages/ui/src/components/project/settings/environment/ProjectSettingsEnvSelector.vue

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,15 @@ const { formatMessage } = useVIntl()
99
1010
const value = defineModel<EnvironmentV3 | undefined>({ required: true })
1111
12+
withDefaults(
13+
defineProps<{
14+
disabled?: boolean
15+
}>(),
16+
{
17+
disabled: false,
18+
},
19+
)
20+
1221
type EnvironmentRadioOption = {
1322
title: MessageDescriptor
1423
description?: MessageDescriptor
@@ -224,6 +233,7 @@ const simulateSave = ref(false)
224233
class="!w-full"
225234
:class="{ 'mt-2': index > 0 }"
226235
:selected="currentOuterOption === key"
236+
:disabled="disabled"
227237
@select="
228238
() => {
229239
if (currentOuterOption !== key) {
@@ -252,6 +262,7 @@ const simulateSave = ref(false)
252262
'opacity-50': currentOuterOption !== key,
253263
}"
254264
:selected="currentSubOption === suboptionKey"
265+
:disabled="disabled"
255266
@select="
256267
() => {
257268
currentOuterOption = key

packages/ui/src/locales/en-US/index.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,12 @@
506506
"project.settings.members.title": {
507507
"defaultMessage": "Members"
508508
},
509+
"project.settings.notice.no-permission.description": {
510+
"defaultMessage": "You don't have permission to edit this."
511+
},
512+
"project.settings.notice.no-permission.title": {
513+
"defaultMessage": "No permission"
514+
},
509515
"project.settings.tags.title": {
510516
"defaultMessage": "Tags"
511517
},

packages/ui/src/providers/project-page.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { Project, ProjectV3Partial } from '@modrinth/utils'
1+
import type { Project, ProjectV3Partial, TeamMember } from '@modrinth/utils'
22
import type { Ref } from 'vue'
33

44
import { createContext } from '.'
@@ -7,6 +7,7 @@ export interface ProjectPageContext {
77
projectV2: Ref<Project>
88
projectV3: Ref<ProjectV3Partial>
99
refreshProject: () => Promise<void>
10+
currentMember: Ref<TeamMember>
1011
}
1112

1213
export const [injectProjectPageContext, provideProjectPageContext] =

packages/ui/src/utils/common-messages.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,14 @@ export const commonProjectSettingsMessages = defineMessages({
331331
id: 'project.settings.members.title',
332332
defaultMessage: 'Members',
333333
},
334+
noPermissionDescription: {
335+
id: 'project.settings.notice.no-permission.description',
336+
defaultMessage: `You don't have permission to edit this.`,
337+
},
338+
noPermissionTitle: {
339+
id: 'project.settings.notice.no-permission.title',
340+
defaultMessage: 'No permission',
341+
},
334342
tags: {
335343
id: 'project.settings.tags.title',
336344
defaultMessage: 'Tags',

packages/utils/changelog.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@ export type VersionEntry = {
1010
}
1111

1212
const VERSIONS: VersionEntry[] = [
13+
{
14+
date: `2025-08-28T18:45:00-07:00`,
15+
product: 'web',
16+
body: `### Improvements
17+
- Fixed modpacks showing an environment migration warning perpetually.
18+
- Fixed environment settings being unclear about permissions.`,
19+
},
1320
{
1421
date: `2025-08-28T16:50:00-07:00`,
1522
product: 'web',

0 commit comments

Comments
 (0)