terriajs
Version:
Geospatial data visualization platform.
104 lines (88 loc) • 3.19 kB
text/typescript
import { action, computed, observable, makeObservable } from "mobx";
import AbstractConstructor from "../Core/AbstractConstructor";
import Model, { BaseModel } from "../Models/Definition/Model";
import ModelTraits from "../Traits/ModelTraits";
type BaseType = Model<ModelTraits>;
/**
* API for setting an access type for the model. Note that the intended use of
* this mixin is just to flag public and private models differently in the UI
* and does not provide any security guarantees.
*
* The implementation is a bit fluid and maybe that makes it a bit hard to
* reason about because we are not strongly typing the possible values for
* `accessType`. For use in frontend, we formally recognizes only one acessType
* which is "public". All other access type values are treated as "private". The
* models overriding this mixin are free to choose any other string valued
* access type for their own purpose.
*/
function AccessControlMixin<T extends AbstractConstructor<BaseType>>(Base: T) {
abstract class _AccessControlMixin extends Base {
private _accessType: string | undefined;
constructor(...args: any[]) {
super(...args);
makeObservable(this);
}
get hasAccessControlMixin() {
return true;
}
/**
* Resolve accessType for this model in the following order:
* 1. Return the access type that was set on this model by explicitly calling setAccessType()
* 2. If this model is referenced by another, return the access type of the referrer
* 3. Return the access type of a parent with valid access type
* 4. If none of the above works - return "public"
*/
get accessType(): string {
// Return the explicitly set accessType
if (this._accessType) {
return this._accessType;
}
// Return the accessType of the referrer.
if (AccessControlMixin.isMixedInto(this.sourceReference)) {
return this.sourceReference.accessType;
}
// Try and return any ancestor's accessType
if (this.knownContainerUniqueIds.length > 0) {
const parentId = this.knownContainerUniqueIds[0];
const parent =
parentId && this.terria.getModelById(BaseModel, parentId);
if (AccessControlMixin.isMixedInto(parent)) {
return parent.accessType;
}
}
// Default
return "public";
}
setAccessType(accessType: string) {
this._accessType = accessType;
}
/**
* Returns true if this model public.
*/
get isPublic() {
return this.accessType === "public";
}
/**
* Returns true if this model is private.
*
* Note that any accessType other than "public" is treated as private.
*/
get isPrivate() {
return this.accessType !== "public";
}
}
return _AccessControlMixin;
}
namespace AccessControlMixin {
export interface Instance extends InstanceType<
ReturnType<typeof AccessControlMixin>
> {}
export function isMixedInto(model: any): model is Instance {
return model && model.hasAccessControlMixin;
}
}
export default AccessControlMixin;