mirror of
https://github.com/turt2live/matrix-dimension.git
synced 2024-10-01 01:05:53 -04:00
Add a button to log everyone out
This commit is contained in:
parent
70c5471df7
commit
0287e472f8
@ -1,10 +1,12 @@
|
|||||||
import { GET, Path, QueryParam } from "typescript-rest";
|
import { GET, Path, POST, QueryParam } from "typescript-rest";
|
||||||
import { ScalarService } from "../scalar/ScalarService";
|
import { ScalarService } from "../scalar/ScalarService";
|
||||||
import config from "../../config";
|
import config from "../../config";
|
||||||
import { ApiError } from "../ApiError";
|
import { ApiError } from "../ApiError";
|
||||||
import { MatrixLiteClient } from "../../matrix/MatrixLiteClient";
|
import { MatrixLiteClient } from "../../matrix/MatrixLiteClient";
|
||||||
import { CURRENT_VERSION } from "../../version";
|
import { CURRENT_VERSION } from "../../version";
|
||||||
import { getFederationConnInfo } from "../../matrix/helpers";
|
import { getFederationConnInfo } from "../../matrix/helpers";
|
||||||
|
import UserScalarToken from "../../db/models/UserScalarToken";
|
||||||
|
import { Cache, CACHE_SCALAR_ACCOUNTS } from "../../MemoryCache";
|
||||||
|
|
||||||
interface DimensionVersionResponse {
|
interface DimensionVersionResponse {
|
||||||
version: string;
|
version: string;
|
||||||
@ -20,6 +22,9 @@ interface DimensionConfigResponse {
|
|||||||
federationHostname: string;
|
federationHostname: string;
|
||||||
clientServerUrl: string;
|
clientServerUrl: string;
|
||||||
};
|
};
|
||||||
|
sessionInfo: {
|
||||||
|
numTokens: number;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -82,6 +87,9 @@ export class AdminService {
|
|||||||
federationHostname: fedInfo.hostname,
|
federationHostname: fedInfo.hostname,
|
||||||
clientServerUrl: config.homeserver.clientServerUrl,
|
clientServerUrl: config.homeserver.clientServerUrl,
|
||||||
},
|
},
|
||||||
|
sessionInfo: {
|
||||||
|
numTokens: await UserScalarToken.count(),
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,4 +103,23 @@ export class AdminService {
|
|||||||
resolvedServer: await getFederationConnInfo(serverName),
|
resolvedServer: await getFederationConnInfo(serverName),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Path("sessions/logout/all")
|
||||||
|
public async logoutAll(@QueryParam("scalar_token") scalarToken: string): Promise<any> {
|
||||||
|
await AdminService.validateAndGetAdminTokenOwner(scalarToken);
|
||||||
|
|
||||||
|
// Clear the cache first to hopefully invalidate a bunch of them
|
||||||
|
Cache.for(CACHE_SCALAR_ACCOUNTS).clear();
|
||||||
|
|
||||||
|
const tokens = await UserScalarToken.all();
|
||||||
|
for (const token of tokens) {
|
||||||
|
await token.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear it again because the delete loop can be slow
|
||||||
|
Cache.for(CACHE_SCALAR_ACCOUNTS).clear();
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
}
|
}
|
@ -28,6 +28,16 @@
|
|||||||
Utility User ID: {{ config.homeserver.userId }}
|
Utility User ID: {{ config.homeserver.userId }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-4">
|
||||||
|
<strong>Sessions</strong><br />
|
||||||
|
Tokens registered: {{ config.sessionInfo.numTokens }}<br />
|
||||||
|
<button class="btn btn-danger btn-sm" type="button" (click)="logoutAll()">
|
||||||
|
Logout Everyone
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</my-ibox>
|
</my-ibox>
|
||||||
</div>
|
</div>
|
@ -1,6 +1,12 @@
|
|||||||
import { Component } from "@angular/core";
|
import { Component } from "@angular/core";
|
||||||
import { AdminApiService } from "../../shared/services/admin/admin-api.service";
|
import { AdminApiService } from "../../shared/services/admin/admin-api.service";
|
||||||
import { FE_DimensionConfig } from "../../shared/models/admin-responses";
|
import { FE_DimensionConfig } from "../../shared/models/admin-responses";
|
||||||
|
import { ToasterService } from "angular2-toaster";
|
||||||
|
import { Modal, overlayConfigFactory } from "ngx-modialog";
|
||||||
|
import {
|
||||||
|
AdminLogoutConfirmationDialogComponent,
|
||||||
|
LogoutConfirmationDialogContext
|
||||||
|
} from "./logout-confirmation/logout-confirmation.component";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
templateUrl: "./home.component.html",
|
templateUrl: "./home.component.html",
|
||||||
@ -11,10 +17,26 @@ export class AdminHomeComponent {
|
|||||||
public isLoading = true;
|
public isLoading = true;
|
||||||
public config: FE_DimensionConfig;
|
public config: FE_DimensionConfig;
|
||||||
|
|
||||||
constructor(adminApi: AdminApiService) {
|
constructor(private adminApi: AdminApiService,
|
||||||
|
private toaster: ToasterService,
|
||||||
|
private modal: Modal) {
|
||||||
adminApi.getConfig().then(config => {
|
adminApi.getConfig().then(config => {
|
||||||
this.config = config;
|
this.config = config;
|
||||||
this.isLoading = false;
|
this.isLoading = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public logoutAll(): void {
|
||||||
|
this.modal.open(AdminLogoutConfirmationDialogComponent, overlayConfigFactory({
|
||||||
|
isBlocking: true,
|
||||||
|
}, LogoutConfirmationDialogContext)).result.then(() => {
|
||||||
|
this.adminApi.logoutAll().then(() => {
|
||||||
|
this.toaster.pop("success", "Everyone has been logged out");
|
||||||
|
this.config.sessionInfo.numTokens = 0;
|
||||||
|
}).catch(err => {
|
||||||
|
console.error(err);
|
||||||
|
this.toaster.pop("error", "Error logging everyone out");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,20 @@
|
|||||||
|
<div class="dialog">
|
||||||
|
<div class="dialog-header">
|
||||||
|
<h4>Logout confirmation</h4>
|
||||||
|
</div>
|
||||||
|
<div class="dialog-content">
|
||||||
|
<p>
|
||||||
|
Logging everyone out will disable all known login tokens for Dimension and upstream integration managers.
|
||||||
|
Most clients will automatically re-register for a login token behind the scenes, similar to how a login token
|
||||||
|
was first acquired.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<button type="button" (click)="dialog.dismiss()" title="close" class="btn btn-secondary btn-sm">
|
||||||
|
<i class="far fa-times-circle"></i> Cancel
|
||||||
|
</button>
|
||||||
|
<button type="button" (click)="dialog.close()" title="logout everyone" class="btn btn-danger btn-sm">
|
||||||
|
<i class="far fa-times-circle"></i> Logout Everyone
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -0,0 +1,15 @@
|
|||||||
|
import { Component } from "@angular/core";
|
||||||
|
import { DialogRef, ModalComponent } from "ngx-modialog";
|
||||||
|
import { BSModalContext } from "ngx-modialog/plugins/bootstrap";
|
||||||
|
|
||||||
|
export class LogoutConfirmationDialogContext extends BSModalContext {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
templateUrl: "./logout-confirmation.component.html",
|
||||||
|
styleUrls: ["./logout-confirmation.component.scss"],
|
||||||
|
})
|
||||||
|
export class AdminLogoutConfirmationDialogComponent implements ModalComponent<LogoutConfirmationDialogContext> {
|
||||||
|
|
||||||
|
constructor(public dialog: DialogRef<LogoutConfirmationDialogContext>) {}
|
||||||
|
}
|
@ -109,6 +109,7 @@ import { SlackBridgeConfigComponent } from "./configs/bridge/slack/slack.bridge.
|
|||||||
import { AdminSlackBridgeManageSelfhostedComponent } from "./admin/bridges/slack/manage-selfhosted/manage-selfhosted.component";
|
import { AdminSlackBridgeManageSelfhostedComponent } from "./admin/bridges/slack/manage-selfhosted/manage-selfhosted.component";
|
||||||
import { AdminSlackBridgeComponent } from "./admin/bridges/slack/slack.component";
|
import { AdminSlackBridgeComponent } from "./admin/bridges/slack/slack.component";
|
||||||
import { AdminSlackApiService } from "./shared/services/admin/admin-slack-api.service";
|
import { AdminSlackApiService } from "./shared/services/admin/admin-slack-api.service";
|
||||||
|
import { AdminLogoutConfirmationDialogComponent } from "./admin/home/logout-confirmation/logout-confirmation.component";
|
||||||
import { ReauthExampleWidgetWrapperComponent } from "./widget-wrappers/reauth-example/reauth-example.component";
|
import { ReauthExampleWidgetWrapperComponent } from "./widget-wrappers/reauth-example/reauth-example.component";
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
@ -199,6 +200,7 @@ import { ReauthExampleWidgetWrapperComponent } from "./widget-wrappers/reauth-ex
|
|||||||
SlackBridgeConfigComponent,
|
SlackBridgeConfigComponent,
|
||||||
AdminSlackBridgeManageSelfhostedComponent,
|
AdminSlackBridgeManageSelfhostedComponent,
|
||||||
AdminSlackBridgeComponent,
|
AdminSlackBridgeComponent,
|
||||||
|
AdminLogoutConfirmationDialogComponent,
|
||||||
ReauthExampleWidgetWrapperComponent,
|
ReauthExampleWidgetWrapperComponent,
|
||||||
|
|
||||||
// Vendor
|
// Vendor
|
||||||
@ -252,6 +254,7 @@ import { ReauthExampleWidgetWrapperComponent } from "./widget-wrappers/reauth-ex
|
|||||||
AdminGitterBridgeManageSelfhostedComponent,
|
AdminGitterBridgeManageSelfhostedComponent,
|
||||||
AdminAddCustomBotComponent,
|
AdminAddCustomBotComponent,
|
||||||
AdminSlackBridgeManageSelfhostedComponent,
|
AdminSlackBridgeManageSelfhostedComponent,
|
||||||
|
AdminLogoutConfirmationDialogComponent,
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class AppModule {
|
export class AppModule {
|
||||||
|
@ -10,6 +10,9 @@ export interface FE_DimensionConfig {
|
|||||||
federationHostname: string;
|
federationHostname: string;
|
||||||
clientServerUrl: string;
|
clientServerUrl: string;
|
||||||
};
|
};
|
||||||
|
sessionInfo: {
|
||||||
|
numTokens: number;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FE_DimensionVersion {
|
export interface FE_DimensionVersion {
|
||||||
|
@ -20,4 +20,8 @@ export class AdminApiService extends AuthedApi {
|
|||||||
public getVersion(): Promise<FE_DimensionVersion> {
|
public getVersion(): Promise<FE_DimensionVersion> {
|
||||||
return this.authedGet("/api/v1/dimension/admin/version").map(r => r.json()).toPromise();
|
return this.authedGet("/api/v1/dimension/admin/version").map(r => r.json()).toPromise();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public logoutAll(): Promise<any> {
|
||||||
|
return this.authedPost("/api/v1/dimension/admin/sessions/logout/all").map(r => r.json()).toPromise();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user