9 Commits

Author SHA1 Message Date
philkunz c8b8013200 1.4.3
Docker (tags) / security (push) Failing after 1s
Docker (tags) / test (push) Has been skipped
Docker (tags) / release (push) Has been skipped
Docker (tags) / metadata (push) Has been skipped
2025-04-03 18:35:38 +00:00
philkunz 0b8639b033 fix(website): Update packageManager configuration in package.json and refine view container background styling 2025-04-03 18:35:38 +00:00
philkunz 08828d6771 update 2024-12-11 01:19:54 +01:00
philkunz aa5cc9ff81 1.4.2
Docker (tags) / security (push) Failing after 0s
Docker (tags) / test (push) Has been skipped
Docker (tags) / release (push) Has been skipped
Docker (tags) / metadata (push) Has been skipped
2024-10-12 23:41:24 +02:00
philkunz 944f689165 fix(UI): Improve text rendering in account navigation. 2024-10-12 23:41:23 +02:00
philkunz 0d613fd634 1.4.1
Docker (tags) / security (push) Failing after 0s
Docker (tags) / test (push) Has been skipped
Docker (tags) / release (push) Has been skipped
Docker (tags) / metadata (push) Has been skipped
2024-10-07 15:14:45 +02:00
philkunz a94d1875bd fix(core): Bug fixes and UI enhancements 2024-10-07 15:14:44 +02:00
philkunz 46844fed58 1.4.0
Docker (tags) / security (push) Failing after 0s
Docker (tags) / test (push) Has been skipped
Docker (tags) / release (push) Has been skipped
Docker (tags) / metadata (push) Has been skipped
2024-10-07 10:26:21 +02:00
philkunz 03a8536297 feat(core): Refactored plugin and request handling to use idpInterfaces 2024-10-07 10:26:21 +02:00
33 changed files with 444 additions and 199 deletions
+37
View File
@@ -1,5 +1,42 @@
# Changelog
## 2025-04-03 - 1.4.3 - fix(website)
Update packageManager configuration in package.json and refine view container background styling
- Add 'packageManager' field in package.json to pin pnpm version
- Adjust background style in ts_web/views/viewcontainer.ts for improved UI consistency
## 2024-12-11 - 1.5.0 - feat(UI)
Added 'Learn more about idp.global' button
- Added a new button for learning more about idp.global in the welcome component
## 2024-12-11 - 1.5.0 - feat(UI)
Added 'Learn more about idp.global' button
- Added a new button for learning more about idp.global in the welcome component
## 2024-10-12 - 1.4.2 - fix(UI)
Improve text rendering in account navigation.
- Fix for text alignment in the commit info section of the account navigation.
- Adjusted font settings for better readability.
## 2024-10-07 - 1.4.1 - fix(core)
Bug fixes and UI enhancements
- Updated packages to resolve compatibility issues.
- Optimized the transition animations for the center container.
- Improved the initialization logic for navigating between views.
- Enhanced UI with better organization selection handling.
## 2024-10-07 - 1.4.0 - feat(core)
Refactored plugin and request handling to use 'idpInterfaces'
- Switched from using 'lointReception' to 'idpInterfaces' in various TypeScript sources.
- Updated references to request and data interfaces across multiple modules.
- Improved account handling with new navigation options.
## 2024-10-07 - 1.3.1 - fix(account)
Fix: updated cleanupViews method to correctly iterate over children.
+4 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@idp.global/idp.global",
"version": "1.3.1",
"version": "1.4.3",
"description": "An identity provider software managing user authentications, registrations, and sessions.",
"main": "dist_ts/index.js",
"typings": "dist_ts/index.d.ts",
@@ -21,7 +21,7 @@
"@api.global/typedserver": "^3.0.51",
"@api.global/typedsocket": "^3.0.1",
"@consentsoftware_private/catalog": "^1.0.73",
"@design.estate/dees-catalog": "^1.1.13",
"@design.estate/dees-catalog": "^1.2.0",
"@design.estate/dees-domtools": "^2.0.64",
"@design.estate/dees-element": "^2.0.39",
"@push.rocks/lik": "^6.0.15",
@@ -101,5 +101,6 @@
"API",
"user data",
"user sessions"
]
],
"packageManager": "pnpm@10.7.0+sha512.6b865ad4b62a1d9842b61d674a393903b871d9244954f652b8842c2b553c72176b278f64c463e52d40fff8aba385c235c8c9ecf5cc7de4fd78b8bb6d49633ab6"
}
+10 -10
View File
@@ -24,8 +24,8 @@ importers:
specifier: ^1.0.73
version: 1.0.77(@types/node@22.7.4)
'@design.estate/dees-catalog':
specifier: ^1.1.13
version: 1.1.13
specifier: ^1.2.0
version: 1.2.0
'@design.estate/dees-domtools':
specifier: ^2.0.64
version: 2.0.64
@@ -420,8 +420,8 @@ packages:
resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==}
engines: {node: '>=12'}
'@design.estate/dees-catalog@1.1.13':
resolution: {integrity: sha512-bgxlsu6rfYCTqyC2tDo8dtwFQB2HaINEK4dOSlvEWd9DmDymphxNoHxi5f/4NFY7H8gSIgUoBmk3y/MFU3GoRg==}
'@design.estate/dees-catalog@1.2.0':
resolution: {integrity: sha512-QVp36XMzX7PEGKJxVaZ09jPFPV2AVYDhNaP1KRWegoiI/PQ3+YilXC7P7WSTPxBojTi28AdPzt9brpaORFY/Qg==}
'@design.estate/dees-comms@1.0.27':
resolution: {integrity: sha512-GvzTUwkV442LD60T08iqSoqvhA02Mou5lFvvqBPc4yBUiU7cZISqBx+76xvMgMIEI9Dx9JfTl4/2nW8MoVAanw==}
@@ -2947,8 +2947,8 @@ packages:
worker-loader:
optional: true
pdfjs-dist@4.6.82:
resolution: {integrity: sha512-BUOryeRFwvbLe0lOU6NhkJNuVQUp06WxlJVVCsxdmJ4y5cU3O3s3/0DunVdK1PMm7v2MUw52qKYaidhDH1Z9+w==}
pdfjs-dist@4.7.76:
resolution: {integrity: sha512-8y6wUgC/Em35IumlGjaJOCm3wV4aY/6sqnIT3fVW/67mXsOZ9HWBn8GDKmJUK0GSzpbmX3gQqwfoFayp78Mtqw==}
engines: {node: '>=18'}
peek-readable@5.2.0:
@@ -4864,7 +4864,7 @@ snapshots:
dependencies:
'@jridgewell/trace-mapping': 0.3.9
'@design.estate/dees-catalog@1.1.13':
'@design.estate/dees-catalog@1.2.0':
dependencies:
'@design.estate/dees-domtools': 2.0.64
'@design.estate/dees-element': 2.0.39
@@ -4882,7 +4882,7 @@ snapshots:
highlight.js: 11.10.0
ibantools: 4.5.1
monaco-editor: 0.52.0
pdfjs-dist: 4.6.82
pdfjs-dist: 4.7.76
xterm: 5.3.0
xterm-addon-fit: 0.8.0(xterm@5.3.0)
transitivePeerDependencies:
@@ -6905,7 +6905,7 @@ snapshots:
'@uptime.link/webwidget@1.1.2':
dependencies:
'@design.estate/dees-catalog': 1.1.13
'@design.estate/dees-catalog': 1.2.0
'@design.estate/dees-domtools': 2.0.64
'@design.estate/dees-element': 2.0.39
'@design.estate/dees-wcctools': 1.0.90
@@ -8563,7 +8563,7 @@ snapshots:
dommatrix: 1.0.3
web-streams-polyfill: 3.3.3
pdfjs-dist@4.6.82:
pdfjs-dist@4.7.76:
optionalDependencies:
canvas: 2.11.2
path2d: 0.2.1
+1 -1
View File
@@ -3,6 +3,6 @@
*/
export const commitinfo = {
name: '@idp.global/idp.global',
version: '1.3.1',
version: '1.4.3',
description: 'An identity provider software managing user authentications, registrations, and sessions.'
}
+2 -2
View File
@@ -3,8 +3,8 @@ import * as path from 'path';
export { path };
// Project scope
import * as lointReception from '../dist_ts_interfaces/index.js';
export { lointReception };
import * as idpInterfaces from '../dist_ts_interfaces/index.js';
export { idpInterfaces };
// @api.global scope
import * as typedserver from '@api.global/typedserver';
+2 -2
View File
@@ -8,7 +8,7 @@ import { User } from './classes.user.js';
@plugins.smartdata.Manager()
export class BillingPlan extends plugins.smartdata.SmartDataDbDoc<
BillingPlan,
plugins.lointReception.data.IBillingPlan,
plugins.idpInterfaces.data.IBillingPlan,
BillingPlanManager
> {
// STATIC
@@ -20,7 +20,7 @@ export class BillingPlan extends plugins.smartdata.SmartDataDbDoc<
public id: string;
@plugins.smartdata.svDb()
public data: plugins.lointReception.data.IBillingPlan['data'] = {
public data: plugins.idpInterfaces.data.IBillingPlan['data'] = {
type: null,
organizationId: null,
lastProcessed: null,
+1 -1
View File
@@ -14,7 +14,7 @@ export class BillingPlanManager {
constructor(receptionRefArg: Reception) {
this.receptionRef = receptionRefArg;
this.receptionRef.typedrouter.addTypedRouter(this.typedrouter);
this.typedrouter.addTypedHandler(new plugins.typedrequest.TypedHandler<plugins.lointReception.request.IReq_UpdatePaymentMethod>('updatePaymentMethod', async reqDataArg => {
this.typedrouter.addTypedHandler(new plugins.typedrequest.TypedHandler<plugins.idpInterfaces.request.IReq_UpdatePaymentMethod>('updatePaymentMethod', async reqDataArg => {
const user = await this.receptionRef.userManager.getUserByJwt(reqDataArg.jwtString);
const organization = await this.receptionRef.organizationmanager.COrganization.getInstance({
id: reqDataArg.orgId,
+3 -3
View File
@@ -6,7 +6,7 @@ import { JwtManager } from './classes.jwtmanager.js';
* Both need to be unique and both can be changed.
*/
@plugins.smartdata.Manager()
export class Jwt extends plugins.smartdata.SmartDataDbDoc<Jwt, plugins.lointReception.data.IJwt, JwtManager> {
export class Jwt extends plugins.smartdata.SmartDataDbDoc<Jwt, plugins.idpInterfaces.data.IJwt, JwtManager> {
// STATIC
public static async createJwtForRefreshToken(
jwtManagerInstance: JwtManager,
@@ -48,7 +48,7 @@ export class Jwt extends plugins.smartdata.SmartDataDbDoc<Jwt, plugins.lointRece
id: jwt.id,
blocked: null,
data: jwt.data,
} as plugins.lointReception.data.IJwt);
} as plugins.idpInterfaces.data.IJwt);
return jwtString;
}
@@ -60,7 +60,7 @@ export class Jwt extends plugins.smartdata.SmartDataDbDoc<Jwt, plugins.lointRece
public blocked: boolean = false;
@plugins.smartdata.svDb()
public data: plugins.lointReception.data.IJwt['data'];
public data: plugins.idpInterfaces.data.IJwt['data'];
public async block() {
this.blocked = true;
+8 -8
View File
@@ -21,7 +21,7 @@ export class JwtManager {
constructor(receptionRefArg: Reception) {
this.receptionRef = receptionRefArg;
this.receptionRef.typedrouter.addTypedRouter(this.typedrouter);
this.typedrouter.addTypedHandler<plugins.lointReception.request.IReq_RefreshJwt>(
this.typedrouter.addTypedHandler<plugins.idpInterfaces.request.IReq_RefreshJwt>(
new plugins.typedrequest.TypedHandler(
'refreshJwt',
async (requestArg) => {
@@ -34,7 +34,7 @@ export class JwtManager {
)
);
this.typedrouter.addTypedHandler(
new plugins.typedrequest.TypedHandler<plugins.lointReception.request.IReq_GetPublicKeyForValidation>(
new plugins.typedrequest.TypedHandler<plugins.idpInterfaces.request.IReq_GetPublicKeyForValidation>(
'getPublicKeyForValidation',
async (requestArg) => {
// TODO control backend token
@@ -46,7 +46,7 @@ export class JwtManager {
);
this.typedrouter.addTypedHandler(
new plugins.typedrequest.TypedHandler<plugins.lointReception.request.IReq_PushOrGetJwtIdBlocklist>(
new plugins.typedrequest.TypedHandler<plugins.idpInterfaces.request.IReq_PushOrGetJwtIdBlocklist>(
'pushOrGetJwtIdBlocklist',
async (requestArg) => {
// TODO control backend token
@@ -60,7 +60,7 @@ export class JwtManager {
public async pushPublicKeyToClients() {
const targetConnections =
await this.receptionRef.options.websiteServer.typedserver.typedsocket.findAllTargetConnectionsByTag<plugins.lointReception.tags.ITag_LolePubapi>(
await this.receptionRef.options.websiteServer.typedserver.typedsocket.findAllTargetConnectionsByTag<plugins.idpInterfaces.tags.ITag_LolePubapi>(
'lole-reception',
{
backendToken: '',
@@ -68,7 +68,7 @@ export class JwtManager {
);
for (const targetConnection of targetConnections) {
const pushPublicKeyTr =
this.receptionRef.options.websiteServer.typedserver.typedsocket.createTypedRequest<plugins.lointReception.request.IReq_PushPublicKeyForValidation>(
this.receptionRef.options.websiteServer.typedserver.typedsocket.createTypedRequest<plugins.idpInterfaces.request.IReq_PushPublicKeyForValidation>(
'pushPublicKeyForValidation',
targetConnection
);
@@ -80,7 +80,7 @@ export class JwtManager {
public async pushBlockedJwtIdListToClients() {
const targetConnections =
await this.receptionRef.options.websiteServer.typedserver.typedsocket.findAllTargetConnectionsByTag<plugins.lointReception.tags.ITag_LolePubapi>(
await this.receptionRef.options.websiteServer.typedserver.typedsocket.findAllTargetConnectionsByTag<plugins.idpInterfaces.tags.ITag_LolePubapi>(
'lole-reception',
{
backendToken: '',
@@ -88,7 +88,7 @@ export class JwtManager {
);
for (const targetConnection of targetConnections) {
const pushPublicKeyTr =
this.receptionRef.options.websiteServer.typedserver.typedsocket.createTypedRequest<plugins.lointReception.request.IReq_PushOrGetJwtIdBlocklist>(
this.receptionRef.options.websiteServer.typedserver.typedsocket.createTypedRequest<plugins.idpInterfaces.request.IReq_PushOrGetJwtIdBlocklist>(
'pushOrGetJwtIdBlocklist',
targetConnection
);
@@ -121,7 +121,7 @@ export class JwtManager {
}
public async verifyJWTAndGetData(jwtArg: string): Promise<Jwt> {
const jwtData: plugins.lointReception.data.IJwt = await this.smartjwtInstance.verifyJWTAndGetData(jwtArg);
const jwtData: plugins.idpInterfaces.data.IJwt = await this.smartjwtInstance.verifyJWTAndGetData(jwtArg);
const jwt = await Jwt.getInstance({
id: jwtData.id,
});
+2 -2
View File
@@ -8,7 +8,7 @@ import { User } from './classes.user.js';
@plugins.smartdata.Manager()
export class LoginSession extends plugins.smartdata.SmartDataDbDoc<
LoginSession,
plugins.lointReception.data.ILoginSession,
plugins.idpInterfaces.data.ILoginSession,
LoginSessionManager
> {
// ======
@@ -55,7 +55,7 @@ export class LoginSession extends plugins.smartdata.SmartDataDbDoc<
public id: string;
@plugins.smartdata.svDb()
public data: plugins.lointReception.data.ILoginSession['data'] = {
public data: plugins.idpInterfaces.data.ILoginSession['data'] = {
userId: null,
validUntil: Date.now() + plugins.smarttime.getMilliSecondsFromUnits({ weeks: 1 }),
invalidated: false,
+9 -9
View File
@@ -26,7 +26,7 @@ export class LoginSessionManager {
this.receptionRef = receptionRefArg;
this.receptionRef.typedrouter.addTypedRouter(this.typedRouter);
this.typedRouter.addTypedHandler(
new plugins.typedrequest.TypedHandler<plugins.lointReception.request.IReq_LoginWithEmailOrUsernameAndPassword>(
new plugins.typedrequest.TypedHandler<plugins.idpInterfaces.request.IReq_LoginWithEmailOrUsernameAndPassword>(
'loginWithEmailOrUsernameAndPassword',
async (requestData) => {
let user = await this.receptionRef.userManager.CUser.getInstance({
@@ -79,7 +79,7 @@ export class LoginSessionManager {
);
this.typedRouter.addTypedHandler(
new plugins.typedrequest.TypedHandler<plugins.lointReception.request.IReq_LoginWithEmail>(
new plugins.typedrequest.TypedHandler<plugins.idpInterfaces.request.IReq_LoginWithEmail>(
'loginWithEmail',
async (requestDataArg) => {
logger.log('info', `loginWithEmail requested for: ${requestDataArg.email}`);
@@ -121,7 +121,7 @@ export class LoginSessionManager {
);
this.typedRouter.addTypedHandler(
new plugins.typedrequest.TypedHandler<plugins.lointReception.request.IReq_LoginWithEmailAfterEmailTokenAquired>(
new plugins.typedrequest.TypedHandler<plugins.idpInterfaces.request.IReq_LoginWithEmailAfterEmailTokenAquired>(
'loginWithEmailAfterEmailTokenAquired',
async (requestArg) => {
const tokenObject = this.emailTokenMap.findSync((itemArg) => {
@@ -145,7 +145,7 @@ export class LoginSessionManager {
)
);
this.typedRouter.addTypedHandler<plugins.lointReception.request.ILogoutRequest>(
this.typedRouter.addTypedHandler<plugins.idpInterfaces.request.ILogoutRequest>(
new plugins.typedrequest.TypedHandler('logout', async (requestDataArg) => {
const loginSession = await this.CLoginSession.getLoginSessionByRefreshToken(requestDataArg.refreshToken);
await loginSession.invalidate();
@@ -153,7 +153,7 @@ export class LoginSessionManager {
})
);
this.typedRouter.addTypedHandler<plugins.lointReception.request.IReq_ExchangeRefreshTokenAndTransferToken>(
this.typedRouter.addTypedHandler<plugins.idpInterfaces.request.IReq_ExchangeRefreshTokenAndTransferToken>(
new plugins.typedrequest.TypedHandler(
'exchangeRefreshTokenAndTransferToken',
async (requestDataArg) => {
@@ -189,7 +189,7 @@ export class LoginSessionManager {
);
this.typedRouter.addTypedHandler(
new plugins.typedrequest.TypedHandler<plugins.lointReception.request.IReq_ResetPassword>(
new plugins.typedrequest.TypedHandler<plugins.idpInterfaces.request.IReq_ResetPassword>(
'resetPassword',
async (requestDataArg) => {
const emailOfPasswordToReset = requestDataArg.email;
@@ -227,7 +227,7 @@ export class LoginSessionManager {
);
this.typedRouter.addTypedHandler(
new plugins.typedrequest.TypedHandler<plugins.lointReception.request.IReq_SetNewPassword>(
new plugins.typedrequest.TypedHandler<plugins.idpInterfaces.request.IReq_SetNewPassword>(
'setNewPassword',
async (requestData) => {
return {
@@ -241,7 +241,7 @@ export class LoginSessionManager {
* returns a device id by simply returning a uuid4
*/
this.typedRouter.addTypedHandler(
new plugins.typedrequest.TypedHandler<plugins.lointReception.request.IReq_ObtainDeviceId>('obtainDeviceId', async (reqData) => {
new plugins.typedrequest.TypedHandler<plugins.idpInterfaces.request.IReq_ObtainDeviceId>('obtainDeviceId', async (reqData) => {
reqData;
return {
deviceId: {
@@ -252,7 +252,7 @@ export class LoginSessionManager {
)
this.typedRouter.addTypedHandler(
new plugins.typedrequest.TypedHandler<plugins.lointReception.request.IReq_AttachDeviceId>('attachDeviceId', async (reqData) => {
new plugins.typedrequest.TypedHandler<plugins.idpInterfaces.request.IReq_AttachDeviceId>('attachDeviceId', async (reqData) => {
// TODO: Blocked by proper JWT handling
reqData.jwt;
return {
+3 -3
View File
@@ -5,7 +5,7 @@ import { User } from './classes.user.js';
@plugins.smartdata.Manager()
export class Organization extends plugins.smartdata.SmartDataDbDoc<
Organization,
plugins.lointReception.data.IOrganization,
plugins.idpInterfaces.data.IOrganization,
OrganizationManager
> {
public static async createNewOrganizationForUser(
@@ -28,10 +28,10 @@ export class Organization extends plugins.smartdata.SmartDataDbDoc<
// INSTANCE
@plugins.smartdata.unI()
id: plugins.lointReception.data.IOrganization['id'];
id: plugins.idpInterfaces.data.IOrganization['id'];
@plugins.smartdata.svDb()
data: plugins.lointReception.data.IOrganization['data'];
data: plugins.idpInterfaces.data.IOrganization['data'];
public async checkIfUserIsAdmin(userArg: User) {
const role = await this.manager.receptionRef.roleManager.getRoleForUserAndOrg(userArg, this);
+2 -2
View File
@@ -17,7 +17,7 @@ export class OrganizationManager {
this.receptionRef.typedrouter.addTypedRouter(this.typedrouter);
this.typedrouter.addTypedHandler(
new plugins.typedrequest.TypedHandler<plugins.lointReception.request.IReq_CreateOrganization>(
new plugins.typedrequest.TypedHandler<plugins.idpInterfaces.request.IReq_CreateOrganization>(
'createOrganization',
async (requestArg) => {
const nameIsAvailable = async () => {
@@ -64,7 +64,7 @@ export class OrganizationManager {
)
);
this.typedrouter.addTypedHandler(
new plugins.typedrequest.TypedHandler<plugins.lointReception.request.IReq_GetOrganizationById>(
new plugins.typedrequest.TypedHandler<plugins.idpInterfaces.request.IReq_GetOrganizationById>(
'getOrganizationById',
async (requestArg) => {
const verifiedJwt = await this.receptionRef.jwtManager.verifyJWTAndGetData(
+1 -1
View File
@@ -68,7 +68,7 @@ export class RegistrationSession {
'announced';
public collectedData: {
userData: plugins.lointReception.data.IUser['data'];
userData: plugins.idpInterfaces.data.IUser['data'];
} = {
userData: {
username: null,
@@ -14,7 +14,7 @@ export class RegistrationSessionManager {
this.receptionRef.typedrouter.addTypedRouter(this.typedRouter);
this.typedRouter.addTypedHandler(
new plugins.typedrequest.TypedHandler<plugins.lointReception.request.IReq_FirstRegistration>(
new plugins.typedrequest.TypedHandler<plugins.idpInterfaces.request.IReq_FirstRegistration>(
'firstRegistrationRequest',
async (requestData) => {
// check for exiting User
@@ -60,7 +60,7 @@ export class RegistrationSessionManager {
);
this.typedRouter.addTypedHandler(
new plugins.typedrequest.TypedHandler<plugins.lointReception.request.IReq_AfterRegistrationEmailClicked>(
new plugins.typedrequest.TypedHandler<plugins.idpInterfaces.request.IReq_AfterRegistrationEmailClicked>(
'afterRegistrationEmailClicked',
async (requestData) => {
console.log(requestData);
@@ -83,7 +83,7 @@ export class RegistrationSessionManager {
);
this.typedRouter.addTypedHandler(
new plugins.typedrequest.TypedHandler<plugins.lointReception.request.IReq_SetDataForRegistration>(
new plugins.typedrequest.TypedHandler<plugins.idpInterfaces.request.IReq_SetDataForRegistration>(
'setDataForRegistration',
async (requestData) => {
const registrationSession = await this.registrationSessions.find(async (itemArg) =>
@@ -111,7 +111,7 @@ export class RegistrationSessionManager {
);
this.typedRouter.addTypedHandler(
new plugins.typedrequest.TypedHandler<plugins.lointReception.request.IReq_MobileVerificationForRegistration>(
new plugins.typedrequest.TypedHandler<plugins.idpInterfaces.request.IReq_MobileVerificationForRegistration>(
'mobileVerificationForRegistration',
async (requestData) => {
const registrationSession = await this.registrationSessions.find(async (itemArg) =>
@@ -157,7 +157,7 @@ export class RegistrationSessionManager {
);
this.typedRouter.addTypedHandler(
new plugins.typedrequest.TypedHandler<plugins.lointReception.request.IReq_FinishRegistration>(
new plugins.typedrequest.TypedHandler<plugins.idpInterfaces.request.IReq_FinishRegistration>(
'finishRegistration',
async (requestData) => {
const registrationSession = await this.registrationSessions.find(async (itemArg) =>
+2 -2
View File
@@ -3,12 +3,12 @@ import * as plugins from '../plugins.js';
@plugins.smartdata.Manager()
export class Role extends plugins.smartdata.SmartDataDbDoc<
Role,
plugins.lointReception.data.IRole
plugins.idpInterfaces.data.IRole
> {
@plugins.smartdata.unI()
id: string;
@plugins.smartdata.svDb()
data: plugins.lointReception.data.IRole['data'];
data: plugins.idpInterfaces.data.IRole['data'];
}
+1 -1
View File
@@ -19,7 +19,7 @@ export class RoleManager {
action: 'create' | 'change' | 'delete';
userId: string;
organizationId: string;
role: plugins.lointReception.data.IRole['data']['role'];
role: plugins.idpInterfaces.data.IRole['data']['role'];
}) {
let returnRole: Role;
switch (optionsArg.action) {
+3 -3
View File
@@ -8,11 +8,11 @@ import { UserManager } from './classes.usermanager.js';
@plugins.smartdata.Manager()
export class User extends plugins.smartdata.SmartDataDbDoc<
User,
plugins.lointReception.data.IUser
plugins.idpInterfaces.data.IUser
> {
// STATIC
public static async createNewUserForUserData(
userDataArg: plugins.lointReception.data.IUser['data']
userDataArg: plugins.idpInterfaces.data.IUser['data']
): Promise<User> {
const newUser = new User();
newUser.id = plugins.smartunique.shortId();
@@ -40,7 +40,7 @@ export class User extends plugins.smartdata.SmartDataDbDoc<
id: string;
@plugins.smartdata.svDb()
public data: plugins.lointReception.data.IUser['data'];
public data: plugins.idpInterfaces.data.IUser['data'];
constructor() {
super();
+25 -2
View File
@@ -19,7 +19,7 @@ export class UserManager {
constructor(receptionRefArg: Reception) {
this.receptionRef = receptionRefArg;
this.receptionRef.typedrouter.addTypedRouter(this.typedrouter);
this.typedrouter.addTypedHandler<plugins.lointReception.request.IReq_GetRolesAndOrganizationsForUserId>(
this.typedrouter.addTypedHandler<plugins.idpInterfaces.request.IReq_GetRolesAndOrganizationsForUserId>(
new plugins.typedrequest.TypedHandler('getRolesAndOrganizationsForUserId', async reqArg => {
console.log('user manager: getting roles and orgs');
const user = await this.getUserByJwtValidation(reqArg.jwt);
@@ -33,6 +33,29 @@ export class UserManager {
}
})
)
this.typedrouter.addTypedHandler<plugins.idpInterfaces.request.IReq_WhoIs>(
new plugins.typedrequest.TypedHandler('whoIs', async reqArg => {
const user = await this.getUserByJwtValidation(reqArg.jwt);
if (!user) {
throw new plugins.typedrequest.TypedResponseError('User not found');
}
return {
user: {
id: user.id,
data: {
name: user.data.name,
username: user.data.username,
email: user.data.email,
mobileNumber: user.data.mobileNumber,
connectedOrgs: user.data.connectedOrgs,
status: null,
password: null,
} as plugins.idpInterfaces.data.IUser['data']
}
}
})
)
}
/**
@@ -51,7 +74,7 @@ export class UserManager {
* faster than the "getUserByJwt"
*/
public async getUserByJwtValidation(jwtStringArg: string) {
const jwtDataArg: plugins.lointReception.data.IJwt = await this.receptionRef.jwtManager.smartjwtInstance.verifyJWTAndGetData(jwtStringArg);
const jwtDataArg: plugins.idpInterfaces.data.IJwt = await this.receptionRef.jwtManager.smartjwtInstance.verifyJWTAndGetData(jwtStringArg);
const resultingUser = await this.CUser.getInstance({
id: jwtDataArg.data.userId
});
+34 -23
View File
@@ -4,19 +4,19 @@ import * as plugins from './plugins.js';
export class IdpClient {
// INSTANCE PRIVATE
private helpers = {
async extractDataFromJwtString(jwtString: string): Promise<plugins.lointReception.data.IJwt> {
async extractDataFromJwtString(jwtString: string): Promise<plugins.idpInterfaces.data.IJwt> {
return plugins.webjwt.getDataFromJwtString(jwtString);
},
};
// INSTANCE PUBLIC
public appData: plugins.lointReception.data.IApp;
public appData: plugins.idpInterfaces.data.IApp;
public rolesReplaySubject = new plugins.smartrx.rxjs.ReplaySubject(1);
public organizationsReplaySubject = new plugins.smartrx.rxjs.ReplaySubject(1);
public parsedReceptionUrl: plugins.smarturl.Smarturl;
constructor(receptionBaseUrlArg: string, appDataArg?: plugins.lointReception.data.IApp) {
constructor(receptionBaseUrlArg: string, appDataArg?: plugins.idpInterfaces.data.IApp) {
if (receptionBaseUrlArg.endsWith('/')) {
receptionBaseUrlArg = receptionBaseUrlArg.slice(0, -1);
}
@@ -78,7 +78,7 @@ export class IdpClient {
public typedrouter = new plugins.typedrequest.TypedRouter();
public statusObservable =
new plugins.smartrx.rxjs.Subject<plugins.lointReception.data.TLoginStatus>();
new plugins.smartrx.rxjs.Subject<plugins.idpInterfaces.data.TLoginStatus>();
public ssoStore = new plugins.webstore.WebStore({
storeName: 'idpglobalStore',
@@ -92,7 +92,7 @@ export class IdpClient {
public async getJwt(): Promise<string> {
return await this.ssoStore.get('idpJwt');
}
public async getJwtData(): Promise<plugins.lointReception.data.IJwt> {
public async getJwtData(): Promise<plugins.idpInterfaces.data.IJwt> {
return this.helpers.extractDataFromJwtString(await this.getJwt());
}
@@ -121,13 +121,13 @@ export class IdpClient {
}
public async refreshJwt(refreshTokenArg?: string): Promise<string> {
let extractedJwt: plugins.lointReception.data.IJwt;
let extractedJwt: plugins.idpInterfaces.data.IJwt;
if (!refreshTokenArg) {
extractedJwt = await this.helpers.extractDataFromJwtString(await this.getJwt());
}
const refreshJwtReq =
new plugins.typedrequest.TypedRequest<plugins.lointReception.request.IReq_RefreshJwt>(
new plugins.typedrequest.TypedRequest<plugins.idpInterfaces.request.IReq_RefreshJwt>(
this.parsedReceptionUrl.toString(),
'refreshJwt'
);
@@ -146,11 +146,11 @@ export class IdpClient {
/**
* can be used to switch between pages
*/
public async getTransferToken(appDataArg?: plugins.lointReception.data.IApp): Promise<string> {
public async getTransferToken(appDataArg?: plugins.idpInterfaces.data.IApp): Promise<string> {
const jwt = await this.performJwtHousekeeping();
const extractedJwt = await this.helpers.extractDataFromJwtString(jwt);
const getTransferToken =
new plugins.typedrequest.TypedRequest<plugins.lointReception.request.IReq_ExchangeRefreshTokenAndTransferToken>(
new plugins.typedrequest.TypedRequest<plugins.idpInterfaces.request.IReq_ExchangeRefreshTokenAndTransferToken>(
this.parsedReceptionUrl.toString(),
'exchangeRefreshTokenAndTransferToken'
);
@@ -188,7 +188,7 @@ export class IdpClient {
const transferToken = url.searchParams['transfertoken'];
if (transferToken) {
const getTransferToken =
new plugins.typedrequest.TypedRequest<plugins.lointReception.request.IReq_ExchangeRefreshTokenAndTransferToken>(
new plugins.typedrequest.TypedRequest<plugins.idpInterfaces.request.IReq_ExchangeRefreshTokenAndTransferToken>(
this.parsedReceptionUrl.toString(),
'exchangeRefreshTokenAndTransferToken'
);
@@ -219,7 +219,8 @@ export class IdpClient {
}
/**
* forces the current user to login
* determines if the user is logged in
* accepts boolean to optionally require login
* @param requireLoginArg
* @returns
*/
@@ -256,22 +257,17 @@ export class IdpClient {
* logs out the current user
*/
public async logout() {
const urlInstance = plugins.smarturl.Smarturl.createFromUrl('https://sso.workspace.global/', {
searchParams: {
appdata: plugins.smartjson.stringifyBase64(this.appData),
action: 'logout',
},
});
if (!globalThis.location.href.startsWith('https://sso.workspace.global/')) {
const idpLogoutUrl = this.parsedReceptionUrl.clone().set('path', '/logout');
if (!globalThis.location.href.startsWith(idpLogoutUrl.origin)) {
// we are somewhere in an app
await this.deleteJwt();
globalThis.location.href = urlInstance.toString();
globalThis.location.href = idpLogoutUrl.toString();
} else {
// we are in the sso page
await this.enableTypedSocket();
console.log(`logging out against ${this.parsedReceptionUrl.toString()}`);
const logoutTr =
this.typedsocket.createTypedRequest<plugins.lointReception.request.ILogoutRequest>(
this.typedsocket.createTypedRequest<plugins.idpInterfaces.request.ILogoutRequest>(
'logout'
);
await logoutTr.fire({
@@ -285,6 +281,9 @@ export class IdpClient {
} else {
console.error('no appData provided. Not redirecting after logout.');
}
if (window.location.href.startsWith(idpLogoutUrl.origin)) {
window.location.href = this.parsedReceptionUrl.origin;
}
}
}
@@ -316,7 +315,7 @@ export class IdpClient {
) {
await this.typedsocketDeferred.promise;
const validateOrg =
this.typedsocket.createTypedRequest<plugins.lointReception.request.IReq_CreateOrganization>(
this.typedsocket.createTypedRequest<plugins.idpInterfaces.request.IReq_CreateOrganization>(
'createOrganization'
);
const response = await validateOrg.fire({
@@ -336,7 +335,7 @@ export class IdpClient {
console.log('idpclient: getting roles and orgs...');
await this.typedsocketDeferred.promise;
const rolesAndOrganizationsForUserId =
this.typedsocket.createTypedRequest<plugins.lointReception.request.IReq_GetRolesAndOrganizationsForUserId>(
this.typedsocket.createTypedRequest<plugins.idpInterfaces.request.IReq_GetRolesAndOrganizationsForUserId>(
'getRolesAndOrganizationsForUserId'
);
const response = await rolesAndOrganizationsForUserId.fire({
@@ -352,7 +351,7 @@ export class IdpClient {
public async updatePaddleCheckoutId(orgIdArg: string, checkoutIdArg: string) {
await this.typedsocketDeferred.promise;
const updateBillingPlan =
this.typedsocket.createTypedRequest<plugins.lointReception.request.IReq_UpdatePaymentMethod>(
this.typedsocket.createTypedRequest<plugins.idpInterfaces.request.IReq_UpdatePaymentMethod>(
'updatePaymentMethod'
);
const response = await updateBillingPlan.fire({
@@ -364,4 +363,16 @@ export class IdpClient {
});
return response;
}
public async whoIs() {
await this.typedsocketDeferred.promise;
const whoIs =
this.typedsocket.createTypedRequest<plugins.idpInterfaces.request.IReq_WhoIs>(
'whoIs'
);
const response = await whoIs.fire({
jwt: await this.getJwt(),
});
return response;
}
}
+7 -7
View File
@@ -11,21 +11,21 @@ export class IdpRequests {
}
public get afterRegistrationEmailClicked () {
return new plugins.typedrequest.TypedRequest<plugins.lointReception.request.IReq_AfterRegistrationEmailClicked>(
return new plugins.typedrequest.TypedRequest<plugins.idpInterfaces.request.IReq_AfterRegistrationEmailClicked>(
this.idpClientArg.parsedReceptionUrl.toString(),
'afterRegistrationEmailClicked'
);
}
public get setData() {
return new plugins.typedrequest.TypedRequest<plugins.lointReception.request.IReq_SetDataForRegistration>(
return new plugins.typedrequest.TypedRequest<plugins.idpInterfaces.request.IReq_SetDataForRegistration>(
this.idpClientArg.parsedReceptionUrl.toString(),
'setDataForRegistration'
);
}
public get mobileNumberVerification () {
return new plugins.typedrequest.TypedRequest<plugins.lointReception.request.IReq_MobileVerificationForRegistration>(
return new plugins.typedrequest.TypedRequest<plugins.idpInterfaces.request.IReq_MobileVerificationForRegistration>(
this.idpClientArg.parsedReceptionUrl.toString(),
'mobileVerificationForRegistration'
);
@@ -33,28 +33,28 @@ export class IdpRequests {
public get finishRegistration() {
return new plugins.typedrequest.TypedRequest<plugins.lointReception.request.IReq_FinishRegistration>(
return new plugins.typedrequest.TypedRequest<plugins.idpInterfaces.request.IReq_FinishRegistration>(
this.idpClientArg.parsedReceptionUrl.toString(),
'finishRegistration'
);
}
public get loginWithUserNameAndPassword () {
return new plugins.typedrequest.TypedRequest<plugins.lointReception.request.IReq_LoginWithEmailOrUsernameAndPassword>(
return new plugins.typedrequest.TypedRequest<plugins.idpInterfaces.request.IReq_LoginWithEmailOrUsernameAndPassword>(
this.idpClientArg.parsedReceptionUrl.toString(),
'loginWithEmailOrUsernameAndPassword'
);
}
public get obtainJwt () {
return new plugins.typedrequest.TypedRequest<plugins.lointReception.request.IReq_RefreshJwt>(
return new plugins.typedrequest.TypedRequest<plugins.idpInterfaces.request.IReq_RefreshJwt>(
this.idpClientArg.parsedReceptionUrl.toString(),
'refreshJwt'
);
}
public get obtainOneTimeToken () {
return new plugins.typedrequest.TypedRequest<plugins.lointReception.request.IReq_ExchangeRefreshTokenAndTransferToken>(
return new plugins.typedrequest.TypedRequest<plugins.idpInterfaces.request.IReq_ExchangeRefreshTokenAndTransferToken>(
this.idpClientArg.parsedReceptionUrl.toString(),
'exchangeRefreshTokenAndTransferToken'
);
+2 -2
View File
@@ -1,7 +1,7 @@
// losslessone_private scope
import * as lointReception from '../dist_ts_interfaces/index.js';
import * as idpInterfaces from '../dist_ts_interfaces/index.js';
export { lointReception };
export { idpInterfaces };
// apiglobal scope
import * as typedrequest from '@api.global/typedrequest';
@@ -74,3 +74,13 @@ export interface IReq_GetRolesAndOrganizationsForUserId
organizations: data.IOrganization[];
};
}
export interface IReq_WhoIs {
method: 'whoIs';
request: {
jwt: string;
};
response: {
user: data.IUser;
};
}
+1 -1
View File
@@ -3,6 +3,6 @@
*/
export const commitinfo = {
name: '@idp.global/idp.global',
version: '1.3.1',
version: '1.4.3',
description: 'An identity provider software managing user authentications, registrations, and sessions.'
}
+16
View File
@@ -110,6 +110,16 @@ export class IdpAccountContent extends DeesElement {
viewcontainer.append(new views.BaseView());
console.log(`loaded base view`);
this.subrouter.on('', async () => {
viewcontainer.classList.add('changing');
await this.domtools.convenience.smartdelay.delayFor(300);
console.log('We are viewing the account overview');
await cleanupViews();
viewcontainer.append(new views.BaseView());
viewcontainer.classList.remove('changing');
await this.domtools.convenience.smartdelay.delayFor(300);
});
this.subrouter.on('/org/:orgName/billing', async () => {
viewcontainer.classList.add('changing');
await this.domtools.convenience.smartdelay.delayFor(300);
@@ -121,5 +131,11 @@ export class IdpAccountContent extends DeesElement {
});
this.subrouter._handleRouteState();
this.registerGarbageFunction(async () => {
this.subrouter.destroy();
})
}
}
+110 -30
View File
@@ -7,11 +7,14 @@ import {
unsafeCSS,
css,
type TemplateResult,
subscribe
subscribe,
} from '@design.estate/dees-element';
import * as plugins from '../../plugins.js';
import * as states from '../../states/accountstate.js';
import { IdpState } from '../../states/idp.state.js';
import { commitinfo } from '../../../dist_ts/00_commitinfo_data.js';
declare global {
interface HTMLElementTagNameMap {
@@ -25,19 +28,19 @@ export class LeleAccountNavigation extends DeesElement {
public options: { text: string; id: string }[] = [
{
id: '1',
text: 'Properties'
text: 'Apps',
},
{
id: '2',
text: 'Users'
text: 'Users',
},
{
id: '3',
text: 'Activity'
text: 'Activity',
},
{
id: '4',
text: 'Billing & Subscription'
text: 'Billing & Subscription',
},
];
@@ -53,20 +56,52 @@ export class LeleAccountNavigation extends DeesElement {
color: ${cssManager.bdTheme('#333', '#fff')};
padding: 10px;
padding-left: 0px;
background: ${cssManager.bdTheme('#eeeeeb', '#111')};
border-right: ${cssManager.bdTheme('1px solid #ccc', '')};
background: ${cssManager.bdTheme('#eeeeeb', '#000')};
border-right: ${cssManager.bdTheme('1px solid #ccc', '1px solid #111')};
}
:host([hidden]) {
display: none;
}
.logo {
font-family: 'Cal Sans';
letter-spacing: 0.0125em;
font-size: 16px;
text-align: center;
padding: 16px 0px 16px 0px;
margin: -8px -8px -16px 0px;
border-bottom: 1px solid #111111;
cursor: default;
position: relative;
z-index: 10;
}
.logo:hover {
background: ${unsafeCSS(plugins.deesCatalog.colors.dark.blue)};
}
.commitinfo {
text-align: center;
position: absolute;
bottom: 0px;
left: 0px;
font-family: 'Intel One Mono';
width: 100%;
font-size: 12px;
padding: 8px;
border-top: ${cssManager.bdTheme('1px solid #ccc', '1px solid #333')};
color: ${cssManager.bdTheme('#666', '#ccc')};
}
.navigationGroupLabel {
width: min-content;
white-space: nowrap;
text-transform: uppercase;
font-size: 12px;
font-weight: 300;
border-bottom: 1px dotted #666;
border-bottom: 1px solid;
border-image: linear-gradient(to right, orange, #44444400) 1;
color: ${cssManager.bdTheme('#666', '#ccc')};
margin-bottom: 5px;
padding-top: 32px;
padding-left: 10px;
@@ -80,11 +115,12 @@ export class LeleAccountNavigation extends DeesElement {
padding: 8px;
padding-left: 10px;
margin-bottom: 5px;
font-size: 14px;
}
.navigationOption:hover {
cursor: pointer;
background: ${cssManager.bdTheme('#bbb', '#333')};
cursor: default;
background: ${cssManager.bdTheme('#bbb', plugins.deesCatalog.colors.dark.blue)};
}
dees-input-dropdown {
margin-top: 16px;
@@ -94,24 +130,64 @@ export class LeleAccountNavigation extends DeesElement {
`,
];
public async getAccountRouter() {
const host = (this.getRootNode() as any).host;
return (host as any).subrouter;
}
public render(): TemplateResult {
return html`
<style></style>
<div class="commitinfo">idp.global v${commitinfo.version}</div>
<div class="logo">idp.global</div>
<div class="navigationGroupLabel">Account Settings</div>
<div
class="navigationOption"
@click=${async () => {
const subrouter = await this.getAccountRouter();
subrouter.pushUrl('');
}}
>
overview
</div>
<div
class="navigationOption"
@click=${async () => {
const idpState = await IdpState.getSingletonInstance();
idpState.domtools.router.pushUrl('/logout');
}}
>
logout
</div>
<div
class="navigationOption"
@click=${async () => {
}}
>
manage roles
</div>
<div
class="navigationOption"
@click=${async () => {
}}
>
create an org
</div>
<div class="navigationGroupLabel">Organization Settings</div>
<dees-input-dropdown .label=${'choose org:'}
<dees-input-dropdown
.label=${'choose org:'}
@selectedOption=${(eventArg: CustomEvent) => {
const currentState = states.accountState.getState()
states.accountState.dispatchAction(states.setSelectedOrg, currentState.organizations.find(org => org.data.slug === eventArg.detail.payload));
const currentState = states.accountState.getState();
states.accountState.dispatchAction(
states.setSelectedOrg,
currentState.organizations.find((org) => org.data.slug === eventArg.detail.payload)
);
}}
></dees-input-dropdown>
${this.options.map(option => {
return html`
<div class="navigationOption">
${option.text}
</div>
`;
${this.options.map((option) => {
return html` <div class="navigationOption">${option.text}</div> `;
})}
<div class="navigationGroupLabel">Account Settings</div>
`;
}
@@ -125,19 +201,23 @@ export class LeleAccountNavigation extends DeesElement {
option: orgArg.data.name,
key: orgArg.data.slug,
payload: orgArg.data.slug,
}
}
states.accountState.select(stateArg => stateArg.organizations).pipe(
plugins.deesDomtools.plugins.smartrx.rxjs.ops.map(orgArrayArg => {
return orgArrayArg.map(orgToMenuEntry)
};
};
states.accountState
.select((stateArg) => stateArg.organizations)
.pipe(
plugins.deesDomtools.plugins.smartrx.rxjs.ops.map((orgArrayArg) => {
return orgArrayArg.map(orgToMenuEntry);
})
).subscribe(menuEntries => {
)
.subscribe((menuEntries) => {
deesInputDropdown.options = menuEntries;
});
states.accountState.select(stateArg => stateArg.selectedOrg).pipe(
plugins.deesDomtools.plugins.smartrx.rxjs.ops.map(orgToMenuEntry)
).subscribe(selectedOrgArg => {
states.accountState
.select((stateArg) => stateArg.selectedOrg)
.pipe(plugins.deesDomtools.plugins.smartrx.rxjs.ops.map(orgToMenuEntry))
.subscribe((selectedOrgArg) => {
deesInputDropdown.selectedOption = selectedOrgArg;
})
});
}
}
+2 -1
View File
@@ -3,7 +3,8 @@ import { css } from '@design.estate/dees-element';
export default css`
h1 {
margin-top: 50px;
border-bottom: 1px solid #666;
border-bottom: 1px solid;
border-image: radial-gradient(rgba(136, 136, 136, 0.44), rgba(136, 136, 136, 0)) 1 / 1 / 0 stretch;
padding-bottom: 10px;
font-weight: 500;
}
+32 -18
View File
@@ -67,24 +67,28 @@ export class BaseView extends DeesElement {
.orgGrid {
display: grid;
grid-gap: 16px;
grid-template-columns: ${cssManager.cssGridColumns(4, 16)}
grid-template-columns: ${cssManager.cssGridColumns(2, 16)};
}
.org {
padding: 16px;
border: 1px dotted #666;
border-radius: 3px;
border-top: 1px solid #444;
background: ${cssManager.bdTheme('#ccc', '#222')};
border-radius: 16px;
}
.org:hover {
cursor: pointer;
cursor: default;
background: ${cssManager.bdTheme('#CCC', '#333')};
}
`,
];
public render() {
return html` <div class="viewHost"></div> `;
return html`
<div class="viewHost">
</div> `;
}
public async firstUpdated(_changedProperties: Map<string | number | symbol, unknown>) {
@@ -147,33 +151,43 @@ export class BaseView extends DeesElement {
subscriptions.push(formSubscription);
button.addEventListener('clicked', async () => {
orgInput.disabled = true;
button.text = 'creating org...'
button.text = 'creating org...';
button.status = 'pending';
hint.innerHTML = 'Waiting for creation of the organization...'
hint.innerHTML = 'Waiting for creation of the organization...';
await state.accountState.dispatchAction(state.manifestNewOrgName, null);
hint.innerHTML = `The Organization with name ${state.accountState.getState().organizations[0].data.name} has been created!`
hint.innerHTML = `The Organization with name ${
state.accountState.getState().organizations[0].data.name
} has been created!`;
button.text = 'created!';
button.status = 'success';
const parentElement = (this.getRootNode() as any).host;
parentElement.subrouter.pushUrl(`/org/${state.accountState.getState().organizations[0].data.slug}/billing`);
parentElement.subrouter.pushUrl(
`/org/${state.accountState.getState().organizations[0].data.slug}/billing`
);
});
} else {
render(html`
render(
html`
<h1>Select An Organization</h1>
<div class="orgGrid">
${state.accountState.getState().organizations.map(orgArg => {
${state.accountState.getState().organizations.map((orgArg) => {
return html`
<div class="org" @click=${() => {
state.accountState.dispatchAction(state.setSelectedOrg, orgArg)
<div
class="org"
@click=${() => {
state.accountState.dispatchAction(state.setSelectedOrg, orgArg);
const parentElement = (this.getRootNode() as any).host;
parentElement.subrouter.pushUrl(`/org/${orgArg.data.slug}/billing`)
}}>
${orgArg.data.name}
parentElement.subrouter.pushUrl(`/org/${orgArg.data.slug}/billing`);
}}
>
<dees-icon .iconFA=${"wallet"} style="display: inline-block; transform: translateY(3px); padding-right: 4px;"></dees-icon> ${orgArg.data.name}
</div>
`
`;
})}
</div>
`, viewHost)
`,
viewHost
);
}
}
}
+3 -3
View File
@@ -47,7 +47,7 @@ export class IdpCenterContainer extends DeesElement {
justify-content: center;
align-items: center;
opacity: 0;
transition: all 0.1s;
transition: all 0.2s;
transition-delay: 0.05s;
transform: translate3d(0px, 8px, 0px);
pointer-events: none;
@@ -126,7 +126,7 @@ export class IdpCenterContainer extends DeesElement {
const done = plugins.smartpromise.defer();
requestAnimationFrame(async () => {
this.shadowRoot.querySelector('.mainContainer').classList.add('show');
await domtoolsInstance.convenience.smartdelay.delayFor(200);
await domtoolsInstance.convenience.smartdelay.delayFor(250);
done.resolve();
});
return done.promise;
@@ -138,7 +138,7 @@ export class IdpCenterContainer extends DeesElement {
const done = plugins.smartpromise.defer();
requestAnimationFrame(async () => {
this.shadowRoot.querySelector('.mainContainer').classList.remove('show');
await domtoolsInstance.convenience.smartdelay.delayFor(200);
await domtoolsInstance.convenience.smartdelay.delayFor(250);
done.resolve();
});
return done.promise;
+6 -1
View File
@@ -111,7 +111,12 @@ export class IdpRegistrationPrompt extends DeesElement {
}
public async firstUpdated() {
const domtoolsInstance = await this.domtoolsPromise;
await this.domtoolsPromise;
const idpState = await IdpState.getSingletonInstance();
const loggedIn = await idpState.idpClient.determineLoginStatus();
if (loggedIn) {
idpState.domtools.router.pushUrl('/');
}
const loginForm: DeesForm = this.shadowRoot.querySelector('#loginForm');
const loginPasswordInput: DeesInputText = loginForm.querySelector('#loginPasswordInput');
const loginSubmitButton: DeesFormSubmit = loginForm.querySelector('#loginSubmitButton');
+73 -39
View File
@@ -9,6 +9,7 @@ import {
cssManager,
unsafeCSS,
css,
resolveExec,
type TemplateResult,
} from '@design.estate/dees-element';
import type { IdpViewcontainer } from '../views/viewcontainer.js';
@@ -34,27 +35,20 @@ export class IdpWelcome extends DeesElement {
display: none;
}
h1 {
font-family: 'Cal Sans';
.maincontainer {
padding: 0px 16px;
}
.greeting {
text-align: center;
font-size: 24px;
margin: 0px auto;
padding: 24px 24px 0px 24px;
width: 500px;
letter-spacing:0.0125em;
}
.textbox {
font-size: 16px;
font-weight: 600;
margin: 24px auto;
width: 500px;
background: #111111;
border-radius: 16px;
border-top: 1px solid ${cssManager.bdTheme('#ffffff', '#222222')};
padding: 24px;
}
.textbox dees-button {
dees-button {
margin-top: 16px;
margin-bottom: 16px;
}
`,
];
@@ -62,31 +56,71 @@ export class IdpWelcome extends DeesElement {
public render(): TemplateResult {
return html`
<style></style>
<h1>idp.global</h1>
<div class="textbox">
Do you want to sign in or register?
<dees-button @click=${async () => {
<idp-centercontainer>
<div class="maincontainer">
${resolveExec(async () => {
const idpState = await IdpState.getSingletonInstance();
idpState.domtools.router.pushUrl('/login');
}}>Sign In</dees-button>
<dees-button @click=${async () => {
await idpState.idpClient.determineLoginStatus();
const data = await idpState.idpClient.whoIs().catch();
if (data?.user) {
return html`
<div class="greeting">Hello ${data.user.data.name}!</div>
<dees-button
@click=${async () => {
const idpState = await IdpState.getSingletonInstance();
idpState.domtools.router.pushUrl('/register');
}}>Register</dees-button>
</div>
<div class="textbox">
Do you want to use idp.global for your app?
<dees-button @click=${() => {}}>Open Developer Dashboard</dees-button>
</div>
<div class="textbox">
idp.global is a Open Source identity provider for the world wide web. You can get the code if you want to improve it.
<dees-button @click=${() => {
window.open('https://code.foss.global/idp.global/idp.global', '_blank');
}}>Get the code</dees-button>
</div>
idpState.domtools.router.pushUrl('/account');
}}
>Manage your account</dees-button
>
<dees-button
@click=${async () => {
const idpState = await IdpState.getSingletonInstance();
idpState.domtools.router.pushUrl('/logout');
}}
>Logout</dees-button
>
`;
}
return html`
Do you want to sign in or register?
<dees-button
@click=${async () => {
const idpState = await IdpState.getSingletonInstance();
idpState.domtools.router.pushUrl('/login');
}}
>Sign In</dees-button
>
<dees-button
@click=${async () => {
const idpState = await IdpState.getSingletonInstance();
idpState.domtools.router.pushUrl('/register');
}}
>Register</dees-button
>
`;
})}
<dees-button @click=${() => {}}>Learn more about idp.global</dees-button>
<dees-button @click=${() => {}}>Open Developer Dashboard</dees-button>
<dees-button
@click=${() => {
window.open('https://code.foss.global/idp.global/idp.global', '_blank');
}}
>Get the Source Code</dees-button
>
</div>
</idp-centercontainer>
`;
}
public async show() {
await this.updateComplete;
const centerContainer = this.shadowRoot.querySelector('idp-centercontainer');
await centerContainer.show();
}
public async hide() {
await this.updateComplete;
const centerContainer = this.shadowRoot.querySelector('idp-centercontainer');
await centerContainer.hide();
}
}
+9 -1
View File
@@ -19,7 +19,7 @@ export class IdpState {
public idpClient = new plugins.idpClient.IdpClient(this.receptionUrl);
public domtools: domtools.DomTools;
public mainStatePart: plugins.deesDomtools.plugins.smartstate.StatePart<'main', {
view: 'welcome' | 'login' | 'register' | 'finishregistration' | 'account';
view: 'welcome' | 'login' | 'register' | 'finishregistration' | 'account' | 'logout';
}>
public async init() {
@@ -44,6 +44,14 @@ export class IdpState {
})
});
this.domtools.router.on('/logout', async () => {
await this.idpClient.logout();
await this.mainStatePart.setState({
...this.mainStatePart.getState(),
view: 'logout',
})
});
this.domtools.router.on('/register', async () => {
await this.mainStatePart.setState({
...this.mainStatePart.getState(),
+5
View File
@@ -33,6 +33,7 @@ export class IdpViewcontainer extends DeesElement {
.viewContainer {
min-width: 100vh;
min-height: 100vh;
background: linear-gradient(-255deg,#06152280 -3.35%,#939eff38 32.79%,#22578480 67.41%,#06152280 97.48%),#212121;
}
`,
];
@@ -59,6 +60,10 @@ export class IdpViewcontainer extends DeesElement {
throw new Error('View container not found in the rendered DOM.');
}
if (!this.currentElement) {
this.currentElement = viewContainer.children[0] as any;
}
// check if current element already is instance of viewElement
if (this.currentElement instanceof viewElement) {
return;