fix: return client id and elevatedUntil on /current/user

This commit is contained in:
Jannis Mattheis
2026-04-11 21:40:25 +02:00
parent 58677b32ef
commit c256025b9f
6 changed files with 109 additions and 11 deletions

View File

@@ -43,7 +43,7 @@ type SessionAPI struct {
// 200:
// description: Ok
// schema:
// $ref: "#/definitions/UserExternal"
// $ref: "#/definitions/CurrentUser"
// headers:
// Set-Cookie:
// type: string
@@ -85,10 +85,12 @@ func (a *SessionAPI) Login(ctx *gin.Context) {
auth.SetCookie(ctx.Writer, client.Token, auth.CookieMaxAge, a.SecureCookie)
ctx.JSON(200, &model.UserExternal{
ID: user.ID,
Name: user.Name,
Admin: user.Admin,
ctx.JSON(200, &model.CurrentUserExternal{
ID: user.ID,
Name: user.Name,
Admin: user.Admin,
ClientID: client.ID,
ElevatedUntil: client.ElevatedUntil,
})
}

View File

@@ -126,7 +126,17 @@ func (a *UserAPI) GetCurrentUser(ctx *gin.Context) {
if success := successOrAbort(ctx, 500, err); !success {
return
}
ctx.JSON(200, toExternalUser(user))
result := &model.CurrentUserExternal{
ID: user.ID,
Name: user.Name,
Admin: user.Admin,
}
client := auth.GetClient(ctx)
if client != nil {
result.ClientID = client.ID
result.ElevatedUntil = client.ElevatedUntil
}
ctx.JSON(200, result)
}
// CreateUser create a user.

View File

@@ -618,7 +618,7 @@
"200": {
"description": "Ok",
"schema": {
"$ref": "#/definitions/UserExternal"
"$ref": "#/definitions/CurrentUser"
},
"headers": {
"Set-Cookie": {
@@ -2623,6 +2623,54 @@
},
"x-go-package": "github.com/gotify/server/v2/model"
},
"CurrentUser": {
"description": "CurrentUserExternal Model",
"type": "object",
"required": [
"id",
"name",
"admin"
],
"properties": {
"admin": {
"description": "If the user is an administrator.",
"type": "boolean",
"x-go-name": "Admin",
"example": true
},
"clientId": {
"description": "The client id of the current session.",
"type": "integer",
"format": "int64",
"x-go-name": "ClientID",
"readOnly": true,
"example": 5
},
"elevatedUntil": {
"description": "The time until which the session is elevated.",
"type": "string",
"format": "date-time",
"x-go-name": "ElevatedUntil",
"readOnly": true
},
"id": {
"description": "The user id.",
"type": "integer",
"format": "int64",
"x-go-name": "ID",
"readOnly": true,
"example": 25
},
"name": {
"description": "The user name. For login.",
"type": "string",
"x-go-name": "Name",
"example": "unicorn"
}
},
"x-go-name": "CurrentUserExternal",
"x-go-package": "github.com/gotify/server/v2/model"
},
"ElevateRequest": {
"type": "object",
"title": "ElevateRequest parameters for client elevation.",

View File

@@ -1,5 +1,7 @@
package model
import "time"
// The User holds information about the credentials of a user and its application and client tokens.
type User struct {
ID uint `gorm:"primaryKey;autoIncrement"`
@@ -80,6 +82,37 @@ type UpdateUserExternal struct {
Pass string `json:"pass,omitempty" form:"pass" query:"pass"`
}
// CurrentUserExternal Model
//
// swagger:model CurrentUser
type CurrentUserExternal struct {
// The user id.
//
// read only: true
// required: true
// example: 25
ID uint `json:"id"`
// The user name. For login.
//
// required: true
// example: unicorn
Name string `json:"name"`
// If the user is an administrator.
//
// required: true
// example: true
Admin bool `json:"admin"`
// The client id of the current session.
//
// read only: true
// example: 5
ClientID uint `json:"clientId,omitempty"`
// The time until which the session is elevated.
//
// read only: true
ElevatedUntil *time.Time `json:"elevatedUntil,omitempty"`
}
// UserExternalPass Model
//
// The Password for updating the user.

View File

@@ -3,7 +3,7 @@ import * as config from './config';
import {detect} from 'detect-browser';
import {SnackReporter} from './snack/SnackManager';
import {observable, runInAction, action} from 'mobx';
import {IUser} from './types';
import {ICurrentUser} from './types';
export class CurrentUser {
private reconnectTimeoutId: number | null = null;
@@ -11,7 +11,7 @@ export class CurrentUser {
@observable accessor loggedIn = false;
@observable accessor refreshKey = 0;
@observable accessor authenticating = true;
@observable accessor user: IUser = {name: 'unknown', admin: false, id: -1};
@observable accessor user: ICurrentUser = {name: 'unknown', admin: false, id: -1};
@observable accessor connectionErrorMessage: string | null = null;
public constructor(private readonly snack: SnackReporter) {}
@@ -58,7 +58,7 @@ export class CurrentUser {
headers: {Authorization: 'Basic ' + btoa(username + ':' + password)},
})
.then(
action((resp: AxiosResponse<IUser>) => {
action((resp: AxiosResponse<ICurrentUser>) => {
this.snack(`A client named '${name}' was created for your session.`);
this.user = resp.data;
this.loggedIn = true;
@@ -75,7 +75,7 @@ export class CurrentUser {
);
};
public tryAuthenticate = async (): Promise<AxiosResponse<IUser>> => {
public tryAuthenticate = async (): Promise<AxiosResponse<ICurrentUser>> => {
return axios
.create()
.get(config.get('url') + 'current/user')

View File

@@ -62,6 +62,11 @@ export interface IUser {
admin: boolean;
}
export interface ICurrentUser extends IUser {
clientId?: number;
elevatedUntil?: string;
}
export interface IVersion {
version: string;
commit: string;