mirror of
https://github.com/stack-auth/stack.git
synced 2026-06-13 21:01:21 +08:00
* added organizations route * added orgganizations/[orgId] and orgganizations/[orgId]/users routes * added more routes * restructured dashboard pages, added organization page * fixed redirect bug * updated sidebar * added mock orgnizations * fixed breadcrumbs * added edit org modal * added memeber table * added permission table * Orgs & perms backend * Fix build errors * updated permission ui * org -> team for frontend * added enable team UI * Stack App for teams * formatted schema * renamed all orgs to teams * fixed docusaurus bug * disabled docusaurus build progress bar * added member profile and direct permission to profile * removed dead code, memberProfile -> member * removed teams attribute from the user object * added /teams endpoint * added create team endpoint * added add-user endpoint * moved add-user * added server side get teams * updated schema formatting * added team enabled endpoints * fixed type error * moved get current teams to current-user/teams * improved interface * added create team * hooked up team to frontend * added hooked up team name with team member page * added list team users * added useUsers to team object * fixed list team user bug * added team update * added list permissions and use permission on app * added create permission * list permission * added permission list * added inherited permission list * add edit permission model * restructured permission graph * updated style * added delete permission * fixed delete permission bug * added inheritence update * fixed await bug * fixed selection bug * added permission update * fixed update bug * fixed team update refresh * added remove user from team * restructured permission and permission definition * updated permission definition structure * updated list permissions and grant permissions * fixed list user permissions * added grant permission * fixed list permission * added direct option to list team use permission * fixed bugs * fixed bugs * added revoke permission * inherited from -> contains * added client list permission * restructured stack-app teams and permissions * fixed server teams and permissions * fixed bug * fixed bugs * added teams pages to demo * added styled component compiler * added list teams * added join and leave teams * fixed prisma onDelete * fixed type bugs * removed on permission change for now * added member * fixed user and server user * fixed imports * added create team * added more content to demo * fixed recursion bug * fixed recursion stack out of bound bug * removed teamsEnabled * added create team on sign-up options * added create team on signup * queriable -> queryable, fixed migration file * fixed migration file * fixed demo build error * fixed license accidental change * fixed tab styling * added required to create permission id * added more ui error hints * fixed seed wrong setting * default team name * improved permission list ui * improved demo display * Update README.md --------- Co-authored-by: Zai Shi <zaishi00@outlook.com>
325 lines
8.8 KiB
TypeScript
325 lines
8.8 KiB
TypeScript
import {
|
|
ClientInterfaceOptions,
|
|
UserJson,
|
|
TokenStore,
|
|
StackClientInterface,
|
|
ReadonlyTokenStore,
|
|
OrglikeJson,
|
|
UserUpdateJson,
|
|
PermissionDefinitionJson,
|
|
PermissionDefinitionScopeJson as PermissionDefinitionScopeJson,
|
|
TeamMemberJson,
|
|
} from "./clientInterface";
|
|
import { Result } from "../utils/results";
|
|
import { ReadonlyJson } from "../utils/json";
|
|
|
|
export type ServerUserJson = UserJson & {
|
|
readonly serverMetadata: ReadonlyJson,
|
|
};
|
|
|
|
export type ServerUserUpdateJson = UserUpdateJson & {
|
|
readonly serverMetadata?: ReadonlyJson,
|
|
readonly primaryEmail?: string | null,
|
|
readonly primaryEmailVerified?: boolean,
|
|
}
|
|
|
|
export type ServerOrglikeCustomizableJson = Pick<ServerOrglikeJson, "displayName">;
|
|
export type ServerOrglikeJson = OrglikeJson & {};
|
|
|
|
export type ServerTeamCustomizableJson = ServerOrglikeCustomizableJson;
|
|
export type ServerTeamJson = ServerOrglikeJson;
|
|
|
|
export type ServerTeamMemberJson = TeamMemberJson
|
|
|
|
export type ServerPermissionDefinitionCustomizableJson = {
|
|
readonly id: string,
|
|
readonly description?: string,
|
|
readonly scope: PermissionDefinitionScopeJson,
|
|
readonly containPermissionIds: string[],
|
|
};
|
|
|
|
export type ServerPermissionDefinitionJson = PermissionDefinitionJson & ServerPermissionDefinitionCustomizableJson & {
|
|
readonly __databaseUniqueId: string,
|
|
readonly scope: PermissionDefinitionScopeJson,
|
|
};
|
|
|
|
export type ServerAuthApplicationOptions = (
|
|
& ClientInterfaceOptions
|
|
& (
|
|
| {
|
|
readonly secretServerKey: string,
|
|
}
|
|
| {
|
|
readonly projectOwnerTokens: ReadonlyTokenStore,
|
|
}
|
|
)
|
|
);
|
|
|
|
|
|
export class StackServerInterface extends StackClientInterface {
|
|
constructor(public override options: ServerAuthApplicationOptions) {
|
|
super(options);
|
|
}
|
|
|
|
protected async sendServerRequest(path: string, options: RequestInit, tokenStore: TokenStore | null, requestType: "server" | "admin" = "server") {
|
|
return await this.sendClientRequest(
|
|
path,
|
|
{
|
|
...options,
|
|
headers: {
|
|
"x-stack-secret-server-key": "secretServerKey" in this.options ? this.options.secretServerKey : "",
|
|
...options.headers,
|
|
},
|
|
},
|
|
tokenStore,
|
|
requestType,
|
|
);
|
|
}
|
|
|
|
async getServerUserByToken(tokenStore: TokenStore): Promise<Result<ServerUserJson>> {
|
|
const response = await this.sendServerRequest(
|
|
"/current-user?server=true",
|
|
{},
|
|
tokenStore,
|
|
);
|
|
const user: ServerUserJson | null = await response.json();
|
|
if (!user) return Result.error(new Error("Failed to get user"));
|
|
return Result.ok(user);
|
|
}
|
|
|
|
async getServerUserById(userId: string): Promise<Result<ServerUserJson>> {
|
|
const response = await this.sendServerRequest(
|
|
`/users/${userId}?server=true`,
|
|
{},
|
|
null,
|
|
);
|
|
const user: ServerUserJson | null = await response.json();
|
|
if (!user) return Result.error(new Error("Failed to get user"));
|
|
return Result.ok(user);
|
|
}
|
|
|
|
async listServerUserTeamPermissions(
|
|
options: {
|
|
teamId: string,
|
|
type: 'global' | 'team',
|
|
direct: boolean,
|
|
},
|
|
tokenStore: TokenStore
|
|
): Promise<ServerPermissionDefinitionJson[]> {
|
|
const response = await this.sendServerRequest(
|
|
`/current-user/teams/${options.teamId}/permissions?type=${options.type}&direct=${options.direct}&server=true`,
|
|
{},
|
|
tokenStore,
|
|
);
|
|
const permissions: ServerPermissionDefinitionJson[] = await response.json();
|
|
return permissions;
|
|
}
|
|
|
|
async listServerUserTeams(tokenStore: TokenStore): Promise<ServerTeamJson[]> {
|
|
const response = await this.sendServerRequest(
|
|
"/current-user/teams?server=true",
|
|
{},
|
|
tokenStore,
|
|
);
|
|
const teams: ServerTeamJson[] = await response.json();
|
|
return teams;
|
|
}
|
|
|
|
async listPermissionDefinitions(): Promise<ServerPermissionDefinitionJson[]> {
|
|
const response = await this.sendServerRequest(`/permission-definitions?server=true`, {}, null);
|
|
return await response.json();
|
|
}
|
|
|
|
async createPermissionDefinition(data: ServerPermissionDefinitionCustomizableJson): Promise<ServerPermissionDefinitionJson> {
|
|
const response = await this.sendServerRequest(
|
|
"/permission-definitions?server=true",
|
|
{
|
|
method: "POST",
|
|
headers: {
|
|
"content-type": "application/json",
|
|
},
|
|
body: JSON.stringify({
|
|
...data,
|
|
scope: {
|
|
type: "any-team",
|
|
}
|
|
}),
|
|
},
|
|
null,
|
|
);
|
|
return await response.json();
|
|
}
|
|
|
|
async updatePermissionDefinition(permissionId: string, data: Partial<ServerPermissionDefinitionCustomizableJson>): Promise<void> {
|
|
await this.sendServerRequest(
|
|
`/permission-definitions/${permissionId}?server=true`,
|
|
{
|
|
method: "PUT",
|
|
headers: {
|
|
"content-type": "application/json",
|
|
},
|
|
body: JSON.stringify(data),
|
|
},
|
|
null,
|
|
);
|
|
}
|
|
|
|
async deletePermissionDefinition(permissionId: string): Promise<void> {
|
|
await this.sendServerRequest(
|
|
`/permission-definitions/${permissionId}?server=true`,
|
|
{ method: "DELETE" },
|
|
null,
|
|
);
|
|
}
|
|
|
|
async listUsers(): Promise<ServerUserJson[]> {
|
|
const response = await this.sendServerRequest("/users?server=true", {}, null);
|
|
return await response.json();
|
|
}
|
|
|
|
async listTeams(): Promise<ServerTeamJson[]> {
|
|
const response = await this.sendServerRequest("/teams?server=true", {}, null);
|
|
return await response.json();
|
|
}
|
|
|
|
async listTeamMembers(teamId: string): Promise<ServerTeamMemberJson[]> {
|
|
const response = await this.sendServerRequest(`/teams/${teamId}/users?server=true`, {}, null);
|
|
return await response.json();
|
|
}
|
|
|
|
async createTeam(data: ServerTeamCustomizableJson): Promise<ServerTeamJson> {
|
|
const response = await this.sendServerRequest(
|
|
"/teams?server=true",
|
|
{
|
|
method: "POST",
|
|
headers: {
|
|
"content-type": "application/json",
|
|
},
|
|
body: JSON.stringify(data),
|
|
},
|
|
null,
|
|
);
|
|
return await response.json();
|
|
}
|
|
|
|
async updateTeam(teamId: string, data: Partial<ServerTeamCustomizableJson>): Promise<void> {
|
|
await this.sendServerRequest(
|
|
`/teams/${teamId}?server=true`,
|
|
{
|
|
method: "PUT",
|
|
headers: {
|
|
"content-type": "application/json",
|
|
},
|
|
body: JSON.stringify(data),
|
|
},
|
|
null,
|
|
);
|
|
}
|
|
|
|
async addUserToTeam(options: {
|
|
userId: string,
|
|
teamId: string,
|
|
}) {
|
|
await this.sendServerRequest(
|
|
`/teams/${options.teamId}/users/${options.userId}?server=true`,
|
|
{
|
|
method: "POST",
|
|
headers: {
|
|
"content-type": "application/json",
|
|
},
|
|
body: JSON.stringify({}),
|
|
},
|
|
null,
|
|
);
|
|
}
|
|
|
|
async removeUserFromTeam(options: {
|
|
userId: string,
|
|
teamId: string,
|
|
}) {
|
|
await this.sendServerRequest(
|
|
`/teams/${options.teamId}/users/${options.userId}?server=true`,
|
|
{
|
|
method: "DELETE",
|
|
headers: {
|
|
"content-type": "application/json",
|
|
},
|
|
body: JSON.stringify({}),
|
|
},
|
|
null,
|
|
);
|
|
}
|
|
|
|
async setServerUserCustomizableData(userId: string, update: ServerUserUpdateJson) {
|
|
await this.sendServerRequest(
|
|
`/users/${userId}?server=true`,
|
|
{
|
|
method: "PUT",
|
|
headers: {
|
|
"content-type": "application/json",
|
|
},
|
|
body: JSON.stringify(update),
|
|
},
|
|
null,
|
|
);
|
|
}
|
|
|
|
async listTeamMemberPermissions(
|
|
options: {
|
|
teamId: string,
|
|
userId: string,
|
|
type: 'global' | 'team',
|
|
direct: boolean,
|
|
}
|
|
): Promise<ServerPermissionDefinitionJson[]> {
|
|
const response = await this.sendServerRequest(
|
|
`/teams/${options.teamId}/users/${options.userId}/permissions?server=true&type=${options.type}&direct=${options.direct}`,
|
|
{},
|
|
null
|
|
);
|
|
return await response.json();
|
|
}
|
|
|
|
async grantTeamUserPermission(teamId: string, userId: string, permissionId: string, type: 'global' | 'team') {
|
|
await this.sendServerRequest(
|
|
`/teams/${teamId}/users/${userId}/permissions/${permissionId}?server=true`,
|
|
{
|
|
method: "POST",
|
|
headers: {
|
|
"content-type": "application/json",
|
|
},
|
|
body: JSON.stringify({ type }),
|
|
},
|
|
null,
|
|
);
|
|
}
|
|
|
|
async revokeTeamUserPermission(teamId: string, userId: string, permissionId: string, type: 'global' | 'team') {
|
|
await this.sendServerRequest(
|
|
`/teams/${teamId}/users/${userId}/permissions/${permissionId}?server=true`,
|
|
{
|
|
method: "DELETE",
|
|
headers: {
|
|
"content-type": "application/json",
|
|
},
|
|
body: JSON.stringify({ type }),
|
|
},
|
|
null,
|
|
);
|
|
}
|
|
|
|
async deleteServerUser(userId: string) {
|
|
await this.sendServerRequest(
|
|
`/users/${userId}?server=true`,
|
|
{
|
|
method: "DELETE",
|
|
headers: {
|
|
"content-type": "application/json",
|
|
},
|
|
body: JSON.stringify({}),
|
|
},
|
|
null,
|
|
);
|
|
}
|
|
}
|