Skip to content

Commit e635a96

Browse files
committed
moar data to one
1 parent bdd686e commit e635a96

File tree

9 files changed

+44
-4
lines changed

9 files changed

+44
-4
lines changed

src/client/Router.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import Courses from './components/Courses'
1414
import Course from './components/Courses/Course'
1515
import NoAccess from './components/NoAccess'
1616
import Chats from './components/Chats'
17+
import Statistics from './components/Admin/Statistics'
1718

1819
const router = createBrowserRouter(
1920
createRoutesFromElements(
@@ -25,6 +26,7 @@ const router = createBrowserRouter(
2526
<Route path="/admin/*" element={<Admin />} />
2627
<Route path="/noaccess" element={<NoAccess />} />
2728
<Route path="/chats" element={<Chats />} />
29+
<Route path="/statistics" element={<Statistics />} />
2830
</Route>
2931
),
3032
{

src/client/components/NavBar/index.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,14 @@ const NavBar = () => {
9090
</Button>
9191
</Link>
9292
)}
93+
{user.isStatsViewer && (
94+
<Link to="/statistics" style={{ textDecoration: 'none' }}>
95+
<Button>
96+
<AdminPanelSettingsOutlined sx={styles.icon} />{' '}
97+
{t('admin:courseStats')}
98+
</Button>
99+
</Link>
100+
)}
93101
<Button
94102
ref={anchorRef}
95103
id="composition-button"

src/client/locales/sv.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,14 @@
6868
"noAccessInfo": "You do not currently have access to CurreChat"
6969
},
7070
"admin": {
71+
"showing": "Showing",
72+
"timePeriodStart": "Starting",
73+
"timePeriodStop": "ending",
74+
"courseStats": "Course stats",
75+
"courseTerms": "Terms",
76+
"courseCodes": "Course codes",
77+
"programCodes": "Programmes",
78+
"studentCount": "Students",
7179
"accessGroups": "Access groups",
7280
"createAccessGroup": "Create new access group",
7381
"confirmAccessGroupDelete": "Are you sure you want to delete this access group?",

src/client/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ export interface User {
4747
hasIamAccess?: boolean
4848
lastRestart: string
4949
enrolledCourses: ChatInstance[]
50+
isStatsViewer: boolean
5051
}
5152

5253
export type Prompt = {

src/server/db/models/chatInstance.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ ChatInstance.init(
5656
model: {
5757
type: DataTypes.STRING,
5858
allowNull: false,
59-
defaultValue: 'gpt-4o-mini',
59+
defaultValue: 'gpt-4o',
6060
},
6161
usageLimit: {
6262
type: DataTypes.INTEGER,

src/server/middleware/user.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { inCI, inDevelopment } from '../../config'
22
import { User as UserModel } from '../db/models'
33
import { User } from '../types'
4-
import { adminIams, powerUserIam } from '../util/config'
4+
import { adminIams, powerUserIam, statsViewerIams } from '../util/config'
55

66
const parseIamGroups = (iamGroups: string) =>
77
iamGroups?.split(';').filter(Boolean) ?? []
@@ -40,6 +40,7 @@ const userMiddleware = async (req: any, _res: any, next: any) => {
4040
iamGroups,
4141
isAdmin: checkAdmin(iamGroups),
4242
isPowerUser: isPowerUser(iamGroups),
43+
isStatsViewer: statsViewerIams.some((iam) => iamGroups.includes(iam)),
4344
}
4445

4546
const adminLoggedInAsId = req.headers['x-admin-logged-in-as']
@@ -49,7 +50,15 @@ const userMiddleware = async (req: any, _res: any, next: any) => {
4950
if (!hijackedUser) {
5051
return next(new Error('User not found'))
5152
}
52-
req.user = { email: acualUser.email, ...hijackedUser.toJSON() }
53+
const isStatsViewer = statsViewerIams.some((iam) =>
54+
hijackedUser.iamGroups.includes(iam)
55+
)
56+
57+
req.user = {
58+
email: acualUser.email,
59+
...hijackedUser.toJSON(),
60+
isStatsViewer,
61+
}
5362
req.hijackedBy = acualUser
5463
} else {
5564
req.user = acualUser

src/server/routes/admin.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,21 @@ import { ChatInstance, UserChatInstanceUsage, User, Prompt } from '../db/models'
66
import { getCourse } from '../util/importer'
77
import { run as runUpdater } from '../updater'
88
import InfoText from '../db/models/infotext'
9+
import { statsViewerIams } from '../util/config'
910

1011
const adminRouter = express.Router()
1112

1213
adminRouter.use((req, _, next) => {
1314
const request = req as RequestWithUser
1415
const { user } = request
1516

16-
if (!user.isAdmin) throw new Error('Unauthorized')
17+
const isStatsViewer = statsViewerIams.some((iam) =>
18+
user.iamGroups.includes(iam)
19+
)
20+
const isAllowed =
21+
user.isAdmin || (isStatsViewer && req.path.includes('/statistics'))
22+
23+
if (!isAllowed) throw new Error('Unauthorized')
1724

1825
return next()
1926
})
@@ -58,6 +65,7 @@ adminRouter.get('/statistics', async (req, res) => {
5865
label: {
5966
en: `spring ${y}`,
6067
fi: `kevät ${y}`,
68+
sv: `vår ${y}`,
6169
},
6270
id,
6371
startDate: `${y}-01-01`,
@@ -68,6 +76,7 @@ adminRouter.get('/statistics', async (req, res) => {
6876
label: {
6977
en: `fall ${y}`,
7078
fi: `syksy ${y}`,
79+
sv: `höst ${y}`,
7180
},
7281
id: id + 1,
7382
startDate: `${y}-08-01`,

src/server/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export interface User {
1414
isPowerUser: boolean
1515
activeCourseIds?: string[]
1616
ownCourses?: string[]
17+
isStatsViewer: boolean
1718
}
1819

1920
export interface RequestWithUser extends Request {

src/server/util/config.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ export const IMPORTER_URL =
3535

3636
export const REDIS_HOST = process.env.REDIS_HOST || 'redis'
3737

38+
export const statsViewerIams = ['hy-one']
39+
3840
export const adminIams = ['grp-toska', 'hy-ypa-opa-ote']
3941

4042
export const basicUserIam = 'grp-currechat'

0 commit comments

Comments
 (0)