Add JRPC API, reworked Login and User pages

This commit is contained in:
Fabian Stamm
2023-04-14 15:13:53 +02:00
parent 922ed1e813
commit e1164eb05b
99 changed files with 4570 additions and 5471 deletions

View File

@ -1,40 +1,40 @@
import DB from "../database";
import { ModelDataBase } from "@hibas123/safe_mongo/lib/model";
import { ObjectID } from "mongodb";
import { v4 } from "uuid";
export interface IClient extends ModelDataBase {
maintainer: ObjectID;
internal: boolean;
name: string;
redirect_url: string;
website: string;
logo?: string;
client_id: string;
client_secret: string;
featured?: boolean;
description?: string;
}
const Client = DB.addModel<IClient>({
name: "client",
versions: [
{
migration: () => {},
schema: {
maintainer: { type: ObjectID },
internal: { type: Boolean, default: false },
name: { type: String },
redirect_url: { type: String },
website: { type: String },
logo: { type: String, optional: true },
client_id: { type: String, default: () => v4() },
client_secret: { type: String },
featured: { type: Boolean, optional: true },
description: { type: String, optional: true },
},
},
],
});
export default Client;
import DB from "../database";
import { ModelDataBase } from "@hibas123/safe_mongo/lib/model";
import { ObjectId } from "mongodb";
import { v4 } from "uuid";
export interface IClient extends ModelDataBase {
maintainer: ObjectId;
internal: boolean;
name: string;
redirect_url: string;
website: string;
logo?: string;
client_id: string;
client_secret: string;
featured?: boolean;
description?: string;
}
const Client = DB.addModel<IClient>({
name: "client",
versions: [
{
migration: () => { },
schema: {
maintainer: { type: ObjectId },
internal: { type: Boolean, default: false },
name: { type: String },
redirect_url: { type: String },
website: { type: String },
logo: { type: String, optional: true },
client_id: { type: String, default: () => v4() },
client_secret: { type: String },
featured: { type: Boolean, optional: true },
description: { type: String, optional: true },
},
},
],
});
export default Client;

View File

@ -1,29 +1,29 @@
import DB from "../database";
import { ModelDataBase } from "@hibas123/safe_mongo/lib/model";
import { ObjectID } from "mongodb";
import { v4 } from "uuid";
export interface IClientCode extends ModelDataBase {
user: ObjectID;
code: string;
client: ObjectID;
permissions: ObjectID[];
validTill: Date;
}
const ClientCode = DB.addModel<IClientCode>({
name: "client_code",
versions: [
{
migration: () => {},
schema: {
user: { type: ObjectID },
code: { type: String },
client: { type: ObjectID },
permissions: { type: Array },
validTill: { type: Date },
},
},
],
});
export default ClientCode;
import DB from "../database";
import { ModelDataBase } from "@hibas123/safe_mongo/lib/model";
import { ObjectId } from "mongodb";
import { v4 } from "uuid";
export interface IClientCode extends ModelDataBase {
user: ObjectId;
code: string;
client: ObjectId;
permissions: ObjectId[];
validTill: Date;
}
const ClientCode = DB.addModel<IClientCode>({
name: "client_code",
versions: [
{
migration: () => { },
schema: {
user: { type: ObjectId },
code: { type: String },
client: { type: ObjectId },
permissions: { type: Array },
validTill: { type: Date },
},
},
],
});
export default ClientCode;

View File

@ -1,25 +1,25 @@
import DB from "../database";
import { ModelDataBase } from "@hibas123/safe_mongo/lib/model";
import { ObjectID } from "mongodb";
export interface IGrant extends ModelDataBase {
user: ObjectID;
client: ObjectID;
permissions: ObjectID[];
}
const Grant = DB.addModel<IGrant>({
name: "grant",
versions: [
{
migration: () => {},
schema: {
user: { type: ObjectID },
client: { type: ObjectID },
permissions: { type: ObjectID, array: true },
},
},
],
});
export default Grant;
import DB from "../database";
import { ModelDataBase } from "@hibas123/safe_mongo/lib/model";
import { ObjectId } from "mongodb";
export interface IGrant extends ModelDataBase {
user: ObjectId;
client: ObjectId;
permissions: ObjectId[];
}
const Grant = DB.addModel<IGrant>({
name: "grant",
versions: [
{
migration: () => { },
schema: {
user: { type: ObjectId },
client: { type: ObjectId },
permissions: { type: ObjectId, array: true },
},
},
],
});
export default Grant;

View File

@ -1,76 +1,76 @@
import DB from "../database";
import { ModelDataBase } from "@hibas123/safe_mongo/lib/model";
import { ObjectID } from "mongodb";
import moment = require("moment");
export interface ILoginToken extends ModelDataBase {
token: string;
special: boolean;
user: ObjectID;
validTill: Date;
valid: boolean;
validated: boolean;
data: any;
ip: string;
browser: string;
}
const LoginToken = DB.addModel<ILoginToken>({
name: "login_token",
versions: [
{
migration: () => {},
schema: {
token: { type: String },
special: { type: Boolean, default: () => false },
user: { type: ObjectID },
validTill: { type: Date },
valid: { type: Boolean },
},
},
{
migration: (doc: ILoginToken) => {
doc.validated = true;
},
schema: {
token: { type: String },
special: { type: Boolean, default: () => false },
user: { type: ObjectID },
validTill: { type: Date },
valid: { type: Boolean },
validated: { type: Boolean, default: false },
},
},
{
migration: (doc: ILoginToken) => {
doc.validated = true;
},
schema: {
token: { type: String },
special: { type: Boolean, default: () => false },
user: { type: ObjectID },
validTill: { type: Date },
valid: { type: Boolean },
validated: { type: Boolean, default: false },
data: { type: "any", optional: true },
ip: { type: String, optional: true },
browser: { type: String, optional: true },
},
},
],
});
export async function CheckToken(
token: ILoginToken,
validated: boolean = true
): Promise<boolean> {
if (!token || !token.valid) return false;
if (validated && !token.validated) return false;
if (moment().isAfter(token.validTill)) {
token.valid = false;
await LoginToken.save(token);
return false;
}
return true;
}
export default LoginToken;
import DB from "../database";
import { ModelDataBase } from "@hibas123/safe_mongo/lib/model";
import { ObjectId } from "mongodb";
import moment = require("moment");
export interface ILoginToken extends ModelDataBase {
token: string;
special: boolean;
user: ObjectId;
validTill: Date;
valid: boolean;
validated: boolean;
data: any;
ip: string;
browser: string;
}
const LoginToken = DB.addModel<ILoginToken>({
name: "login_token",
versions: [
{
migration: () => { },
schema: {
token: { type: String },
special: { type: Boolean, default: () => false },
user: { type: ObjectId },
validTill: { type: Date },
valid: { type: Boolean },
},
},
{
migration: (doc: ILoginToken) => {
doc.validated = true;
},
schema: {
token: { type: String },
special: { type: Boolean, default: () => false },
user: { type: ObjectId },
validTill: { type: Date },
valid: { type: Boolean },
validated: { type: Boolean, default: false },
},
},
{
migration: (doc: ILoginToken) => {
doc.validated = true;
},
schema: {
token: { type: String },
special: { type: Boolean, default: () => false },
user: { type: ObjectId },
validTill: { type: Date },
valid: { type: Boolean },
validated: { type: Boolean, default: false },
data: { type: "any", optional: true },
ip: { type: String, optional: true },
browser: { type: String, optional: true },
},
},
],
});
export async function CheckToken(
token: ILoginToken,
validated: boolean = true
): Promise<boolean> {
if (!token || !token.valid) return false;
if (validated && !token.validated) return false;
if (moment().isAfter(token.validTill)) {
token.valid = false;
await LoginToken.save(token);
return false;
}
return true;
}
export default LoginToken;

View File

@ -1,37 +1,37 @@
import DB from "../database";
import { ModelDataBase } from "@hibas123/safe_mongo/lib/model";
import { ObjectID } from "mongodb";
export interface IPermission extends ModelDataBase {
name: string;
description: string;
client: ObjectID;
grant_type: "user" | "client";
}
const Permission = DB.addModel<IPermission>({
name: "permission",
versions: [
{
migration: () => {},
schema: {
name: { type: String },
description: { type: String },
client: { type: ObjectID },
},
},
{
migration: (old) => {
old.grant_type = "user";
},
schema: {
name: { type: String },
description: { type: String },
client: { type: ObjectID },
grant_type: { type: String, default: "user" },
},
},
],
});
export default Permission;
import DB from "../database";
import { ModelDataBase } from "@hibas123/safe_mongo/lib/model";
import { ObjectId } from "mongodb";
export interface IPermission extends ModelDataBase {
name: string;
description: string;
client: ObjectId;
grant_type: "user" | "client";
}
const Permission = DB.addModel<IPermission>({
name: "permission",
versions: [
{
migration: () => { },
schema: {
name: { type: String },
description: { type: String },
client: { type: ObjectId },
},
},
{
migration: (old) => {
old.grant_type = "user";
},
schema: {
name: { type: String },
description: { type: String },
client: { type: ObjectId },
grant_type: { type: String, default: "user" },
},
},
],
});
export default Permission;

View File

@ -1,32 +1,32 @@
import DB from "../database";
import { ModelDataBase } from "@hibas123/safe_mongo/lib/model";
import { ObjectID } from "mongodb";
import { v4 } from "uuid";
export interface IRefreshToken extends ModelDataBase {
token: string;
user: ObjectID;
client: ObjectID;
permissions: ObjectID[];
validTill: Date;
valid: boolean;
}
const RefreshToken = DB.addModel<IRefreshToken>({
name: "refresh_token",
versions: [
{
migration: () => {},
schema: {
token: { type: String },
user: { type: ObjectID },
client: { type: ObjectID },
permissions: { type: Array },
validTill: { type: Date },
valid: { type: Boolean },
},
},
],
});
export default RefreshToken;
import DB from "../database";
import { ModelDataBase } from "@hibas123/safe_mongo/lib/model";
import { ObjectId } from "mongodb";
import { v4 } from "uuid";
export interface IRefreshToken extends ModelDataBase {
token: string;
user: ObjectId;
client: ObjectId;
permissions: ObjectId[];
validTill: Date;
valid: boolean;
}
const RefreshToken = DB.addModel<IRefreshToken>({
name: "refresh_token",
versions: [
{
migration: () => { },
schema: {
token: { type: String },
user: { type: ObjectId },
client: { type: ObjectId },
permissions: { type: Array },
validTill: { type: Date },
valid: { type: Boolean },
},
},
],
});
export default RefreshToken;

View File

@ -1,57 +1,57 @@
import DB from "../database";
import { ModelDataBase } from "@hibas123/safe_mongo/lib/model";
import { ObjectID } from "mongodb";
import { v4 } from "uuid";
export interface IRegCode extends ModelDataBase {
token: string;
valid: boolean;
validTill: Date;
}
const RegCode = DB.addModel<IRegCode>({
name: "reg_code",
versions: [
{
migration: () => {},
schema: {
token: { type: String },
valid: { type: Boolean },
validTill: { type: Date },
},
},
],
});
export default RegCode;
// import { Model, Table, Column, ForeignKey, BelongsTo, Unique, CreatedAt, UpdatedAt, DeletedAt, HasMany, BelongsToMany, Default, DataType } from "sequelize-typescript"
// import User from "./user";
// import Permission from "./permissions";
// import RefreshPermission from "./refresh_permission";
// @Table
// export default class RegCode extends Model<RegCode> {
// @Unique
// @Default(DataType.UUIDV4)
// @Column(DataType.UUID)
// token: string
// @Column
// validTill: Date
// @Column
// valid: boolean
// @Column
// @CreatedAt
// creationDate: Date;
// @Column
// @UpdatedAt
// updatedOn: Date;
// @Column
// @DeletedAt
// deletionDate: Date;
// }
import DB from "../database";
import { ModelDataBase } from "@hibas123/safe_mongo/lib/model";
import { ObjectId } from "mongodb";
import { v4 } from "uuid";
export interface IRegCode extends ModelDataBase {
token: string;
valid: boolean;
validTill: Date;
}
const RegCode = DB.addModel<IRegCode>({
name: "reg_code",
versions: [
{
migration: () => { },
schema: {
token: { type: String },
valid: { type: Boolean },
validTill: { type: Date },
},
},
],
});
export default RegCode;
// import { Model, Table, Column, ForeignKey, BelongsTo, Unique, CreatedAt, UpdatedAt, DeletedAt, HasMany, BelongsToMany, Default, DataType } from "sequelize-typescript"
// import User from "./user";
// import Permission from "./permissions";
// import RefreshPermission from "./refresh_permission";
// @Table
// export default class RegCode extends Model<RegCode> {
// @Unique
// @Default(DataType.UUIDV4)
// @Column(DataType.UUID)
// token: string
// @Column
// validTill: Date
// @Column
// valid: boolean
// @Column
// @CreatedAt
// creationDate: Date;
// @Column
// @UpdatedAt
// updatedOn: Date;
// @Column
// @DeletedAt
// deletionDate: Date;
// }

View File

@ -1,69 +1,71 @@
import DB from "../database";
import { ModelDataBase } from "@hibas123/safe_mongo/lib/model";
import { ObjectID } from "bson";
export enum TFATypes {
TOTP,
BACKUP_CODE,
WEBAUTHN,
APP_ALLOW,
}
export const TFANames = new Map<TFATypes, string>();
TFANames.set(TFATypes.TOTP, "Authenticator");
TFANames.set(TFATypes.BACKUP_CODE, "Backup Codes");
TFANames.set(TFATypes.WEBAUTHN, "Security Key (WebAuthn)");
TFANames.set(TFATypes.APP_ALLOW, "App Push");
export interface ITwoFactor extends ModelDataBase {
user: ObjectID;
valid: boolean;
expires?: Date;
name?: string;
type: TFATypes;
data: any;
}
export interface IOTC extends ITwoFactor {
data: string;
}
export interface IYubiKey extends ITwoFactor {
data: {
registration?: any;
publicKey: string;
keyHandle: string;
};
}
export interface IU2F extends ITwoFactor {
data: {
challenge?: string;
publicKey: string;
keyHandle: string;
registration?: string;
};
}
export interface IBackupCode extends ITwoFactor {
data: string[];
}
const TwoFactor = DB.addModel<ITwoFactor>({
name: "twofactor",
versions: [
{
migration: (e) => { },
schema: {
user: { type: ObjectID },
valid: { type: Boolean },
expires: { type: Date, optional: true },
name: { type: String, optional: true },
type: { type: Number },
data: { type: "any" },
},
},
],
});
export default TwoFactor;
import { TFAType } from "@hibas123/openauth-internalapi";
import DB from "../database";
import { ModelDataBase } from "@hibas123/safe_mongo/lib/model";
import { ObjectId } from "bson";
import { Binary } from "mongodb";
export { TFAType as TFATypes };
export const TFANames = new Map<TFAType, string>();
TFANames.set(TFAType.TOTP, "Authenticator");
TFANames.set(TFAType.BACKUP_CODE, "Backup Codes");
TFANames.set(TFAType.WEBAUTHN, "Security Key (WebAuthn)");
TFANames.set(TFAType.APP_ALLOW, "App Push");
export interface ITwoFactor extends ModelDataBase {
user: ObjectId;
valid: boolean;
expires?: Date;
name?: string;
type: TFAType;
data: any;
}
export interface ITOTP extends ITwoFactor {
data: string;
}
export interface IWebAuthn extends ITwoFactor {
data: {
challenge?: any;
device?: {
credentialID: Binary;
credentialPublicKey: Binary;
counter: number;
transports: AuthenticatorTransport[]
}
};
}
export interface IU2F extends ITwoFactor {
data: {
challenge?: string;
publicKey: string;
keyHandle: string;
registration?: string;
};
}
export interface IBackupCode extends ITwoFactor {
data: string[];
}
const TwoFactor = DB.addModel<ITwoFactor>({
name: "twofactor",
versions: [
{
migration: (e) => { },
schema: {
user: { type: ObjectId },
valid: { type: Boolean },
expires: { type: Date, optional: true },
name: { type: String, optional: true },
type: { type: Number },
data: { type: "any" },
},
},
],
});
export default TwoFactor;

View File

@ -1,134 +1,134 @@
import DB from "../database";
import { ModelDataBase } from "@hibas123/safe_mongo/lib/model";
import { ObjectID } from "mongodb";
import { v4 } from "uuid";
import { randomString } from "../helper/random";
export enum Gender {
none,
male,
female,
other,
}
export interface IUser extends ModelDataBase {
uid: string;
username: string;
name: string;
birthday?: Date;
gender: Gender;
admin: boolean;
password: string;
salt: string;
mails: ObjectID[];
phones: { phone: string; verified: boolean; primary: boolean }[];
encryption_key: string;
}
const User = DB.addModel<IUser>({
name: "user",
versions: [
{
migration: () => {},
schema: {
uid: { type: String, default: () => v4() },
username: { type: String },
name: { type: String },
birthday: { type: Date, optional: true },
gender: { type: Number },
admin: { type: Boolean },
password: { type: String },
salt: { type: String },
mails: { type: Array, default: () => [] },
phones: {
array: true,
model: true,
type: {
phone: { type: String },
verified: { type: Boolean },
primary: { type: Boolean },
},
},
twofactor: {
array: true,
model: true,
type: {
token: { type: String },
valid: { type: Boolean },
type: { type: Number },
},
},
},
},
{
migration: (e: IUser) => {
e.encryption_key = randomString(64);
},
schema: {
uid: { type: String, default: () => v4() },
username: { type: String },
name: { type: String },
birthday: { type: Date, optional: true },
gender: { type: Number },
admin: { type: Boolean },
password: { type: String },
salt: { type: String },
mails: { type: Array, default: () => [] },
phones: {
array: true,
model: true,
type: {
phone: { type: String },
verified: { type: Boolean },
primary: { type: Boolean },
},
},
twofactor: {
array: true,
model: true,
type: {
token: { type: String },
valid: { type: Boolean },
type: { type: Number },
},
},
encryption_key: {
type: String,
default: () => randomString(64),
},
},
},
{
migration: (e: any) => {
delete e.twofactor;
},
schema: {
uid: { type: String, default: () => v4() },
username: { type: String },
name: { type: String },
birthday: { type: Date, optional: true },
gender: { type: Number },
admin: { type: Boolean },
password: { type: String },
salt: { type: String },
mails: { type: Array, default: () => [] },
phones: {
array: true,
model: true,
type: {
phone: { type: String },
verified: { type: Boolean },
primary: { type: Boolean },
},
},
encryption_key: {
type: String,
default: () => randomString(64),
},
},
},
],
});
export default User;
import DB from "../database";
import { ModelDataBase } from "@hibas123/safe_mongo/lib/model";
import { ObjectId } from "mongodb";
import { v4 } from "uuid";
import { randomString } from "../helper/random";
export enum Gender {
none,
male,
female,
other,
}
export interface IUser extends ModelDataBase {
uid: string;
username: string;
name: string;
birthday?: Date;
gender: Gender;
admin: boolean;
password: string;
salt: string;
mails: ObjectId[];
phones: { phone: string; verified: boolean; primary: boolean }[];
encryption_key: string;
}
const User = DB.addModel<IUser>({
name: "user",
versions: [
{
migration: () => { },
schema: {
uid: { type: String, default: () => v4() },
username: { type: String },
name: { type: String },
birthday: { type: Date, optional: true },
gender: { type: Number },
admin: { type: Boolean },
password: { type: String },
salt: { type: String },
mails: { type: Array, default: () => [] },
phones: {
array: true,
model: true,
type: {
phone: { type: String },
verified: { type: Boolean },
primary: { type: Boolean },
},
},
twofactor: {
array: true,
model: true,
type: {
token: { type: String },
valid: { type: Boolean },
type: { type: Number },
},
},
},
},
{
migration: (e: IUser) => {
e.encryption_key = randomString(64);
},
schema: {
uid: { type: String, default: () => v4() },
username: { type: String },
name: { type: String },
birthday: { type: Date, optional: true },
gender: { type: Number },
admin: { type: Boolean },
password: { type: String },
salt: { type: String },
mails: { type: Array, default: () => [] },
phones: {
array: true,
model: true,
type: {
phone: { type: String },
verified: { type: Boolean },
primary: { type: Boolean },
},
},
twofactor: {
array: true,
model: true,
type: {
token: { type: String },
valid: { type: Boolean },
type: { type: Number },
},
},
encryption_key: {
type: String,
default: () => randomString(64),
},
},
},
{
migration: (e: any) => {
delete e.twofactor;
},
schema: {
uid: { type: String, default: () => v4() },
username: { type: String },
name: { type: String },
birthday: { type: Date, optional: true },
gender: { type: Number },
admin: { type: Boolean },
password: { type: String },
salt: { type: String },
mails: { type: Array, default: () => [] },
phones: {
array: true,
model: true,
type: {
phone: { type: String },
verified: { type: Boolean },
primary: { type: Boolean },
},
},
encryption_key: {
type: String,
default: () => randomString(64),
},
},
},
],
});
export default User;