small changes

This commit is contained in:
2023-01-18 14:37:34 +01:00
parent 327f570316
commit 136ad48a5e
13 changed files with 148 additions and 56 deletions

View File

@@ -156,8 +156,41 @@ export default class API {
}
async updateProfile(username=null, fullName=null, password=null, confirmPassword = null, oldPassword = null) {
return this.apiCall("user/updateProfile", { username: username, fullName: fullName,
let res = await this.apiCall("user/updateProfile", { username: username, fullName: fullName,
password: password, confirmPassword: confirmPassword, oldPassword: oldPassword });
if (res.success) {
if (username !== null) {
this.user.name = username;
}
if (fullName !== null) {
this.user.fullName = fullName;
}
}
return res;
}
async uploadPicture(file, scale=1.0) {
const formData = new FormData();
formData.append("scale", scale);
formData.append("picture", file, file.name);
let res = await this.apiCall("user/uploadPicture", formData);
if (res.success) {
this.user.profilePicture = res.profilePicture;
}
return res;
}
async removePicture() {
let res = await this.apiCall("user/removePicture");
if (res.success) {
this.user.profilePicture = null;
}
return res;
}
/** Stats **/
@@ -234,8 +267,8 @@ export default class API {
}
/** ApiKeyAPI **/
async getApiKeys(showActiveOnly = false) {
return this.apiCall("apiKey/fetch", { showActiveOnly: showActiveOnly });
async getApiKeys(showActiveOnly = false, page = 1, count = 25, orderBy = "validUntil", sortOrder = "desc") {
return this.apiCall("apiKey/fetch", { showActiveOnly: showActiveOnly, pageNum: page, count: count, orderBy: orderBy, sortOrder: sortOrder });
}
async createApiKey() {
@@ -248,11 +281,21 @@ export default class API {
/** 2FA API **/
async confirmTOTP(code) {
return this.apiCall("tfa/confirmTotp", { code: code });
let res = await this.apiCall("tfa/confirmTotp", { code: code });
if (res.success) {
this.user.twoFactorToken = { type: "totp", confirmed: true };
}
return res;
}
async remove2FA(password) {
return this.apiCall("tfa/remove", { password: password });
let res = await this.apiCall("tfa/remove", { password: password });
if (res.success) {
this.user.twoFactorToken = null;
}
return res;
}
async verifyTotp2FA(code) {
@@ -264,12 +307,22 @@ export default class API {
}
async register2FA(clientDataJSON = null, attestationObject = null) {
return this.apiCall("tfa/registerKey", { clientDataJSON: clientDataJSON, attestationObject: attestationObject });
let res = await this.apiCall("tfa/registerKey", { clientDataJSON: clientDataJSON, attestationObject: attestationObject });
if (res.success && res.twoFactorToken) {
this.user.twoFactorToken = res.twoFactorToken;
}
return res;
}
/** GPG API **/
async uploadGPG(pubkey) {
return this.apiCall("user/importGPG", { pubkey: pubkey });
let res = await this.apiCall("user/importGPG", { pubkey: pubkey });
if (res.success) {
this.user.gpgKey = res.gpgKey;
}
return res;
}
async confirmGpgToken(token) {

View File

@@ -7,7 +7,6 @@ import {LocaleContext} from "../locale";
import clsx from "clsx";
import {Box, IconButton} from "@mui/material";
import {formatDateTime} from "../util";
import UserLink from "security-lab/src/elements/user/userlink";
import CachedIcon from "@material-ui/icons/Cached";
@@ -137,6 +136,7 @@ export class DataColumn {
this.field = field;
this.sortable = !params.hasOwnProperty("sortable") || !!params.sortable;
this.align = params.align || "left";
this.params = params;
}
renderData(L, entry, index) {
@@ -152,6 +152,16 @@ export class StringColumn extends DataColumn {
constructor(label, field = null, params = {}) {
super(label, field, params);
}
renderData(L, entry, index) {
let data = super.renderData(L, entry, index);
if (this.params.style) {
data = <span style={this.params.style}>{data}</span>
}
return data;
}
}
export class NumericColumn extends DataColumn {
@@ -198,13 +208,14 @@ export class DateTimeColumn extends DataColumn {
}
}
export class UserLinkColumn extends DataColumn {
export class BoolColumn extends DataColumn {
constructor(label, field = null, params = {}) {
super(label, field, params);
}
renderData(L, entry, index) {
return <UserLink user={super.renderData(L, entry)}/>
let data = super.renderData(L, entry);
return L(data ? "general.true" : "general.false");
}
}

View File

@@ -1,7 +1,7 @@
import React from "react";
import clsx from "clsx";
import {Box, Modal} from "@mui/material";
import {Button, Typography} from "@material-ui/core";
import React, {useContext} from "react";
import {Dialog as MuiDialog, DialogActions, DialogContent, DialogContentText, DialogTitle} from "@mui/material";
import {Button} from "@material-ui/core";
import {LocaleContext} from "../locale";
import "./dialog.css";
export default function Dialog(props) {
@@ -11,6 +11,8 @@ export default function Dialog(props) {
const onOption = props.onOption || function() { };
const options = props.options || ["Close"];
const type = props.type || "default";
const {translate: L} = useContext(LocaleContext);
let buttons = [];
for (let name of options) {
@@ -26,20 +28,19 @@ export default function Dialog(props) {
)
}
return <Modal
return <MuiDialog
open={show}
onClose={onClose}
aria-labelledby="modal-title"
aria-describedby="modal-description"
>
<Box className={clsx("modal-dialog", props.className)}>
<Typography id="modal-title" variant="h6" component="h2">
{props.title}
</Typography>
<Typography id="modal-description" sx={{ mt: 2 }}>
{props.message}
</Typography>
{ buttons }
</Box>
</Modal>
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description">
<DialogTitle>{ props.title }</DialogTitle>
<DialogContent>
<DialogContentText>
{ props.message }
</DialogContentText>
</DialogContent>
<DialogActions>
{buttons}
</DialogActions>
</MuiDialog>
}

View File

@@ -185,7 +185,7 @@ export default function LoginForm(props) {
}).catch(e => {
set2FAToken({ ...tfaToken, step: 2, error: e.toString() });
});
}, [api.loggedIn, tfaToken, props.onLogin, abortSignal]);
}, [api.loggedIn, tfaToken, props.onLogin, props.onKey2FA, abortSignal]);
const createForm = () => {
@@ -335,7 +335,10 @@ export default function LoginForm(props) {
}
if (!loaded) {
return <b>{L("general.loading")} <Icon icon={"spinner"}/></b>
return <Box textAlign={"center"} mt={2}>
<h2>{L("general.loading", "Loading")}</h2>
<CircularProgress size={"32px"}/>
</Box>
}
let successMessage = getParameter("success");