Removed user groups
ci/woodpecker/manual/ociImageTag Pipeline was successful Details

This commit is contained in:
Natty 2024-01-07 02:42:33 +01:00
parent b918db7a53
commit 6a66010294
Signed by: natty
GPG Key ID: BF6CB659ADEE60EC
34 changed files with 27 additions and 1185 deletions

View File

@ -26,9 +26,6 @@ import {SwSubscription} from "@/models/entities/sw-subscription.js";
import {Blocking} from "@/models/entities/blocking.js";
import {UserList} from "@/models/entities/user-list.js";
import {UserListJoining} from "@/models/entities/user-list-joining.js";
import {UserGroup} from "@/models/entities/user-group.js";
import {UserGroupJoining} from "@/models/entities/user-group-joining.js";
import {UserGroupInvitation} from "@/models/entities/user-group-invitation.js";
import {Hashtag} from "@/models/entities/hashtag.js";
import {NoteFavorite} from "@/models/entities/note-favorite.js";
import {AbuseUserReport} from "@/models/entities/abuse-user-report.js";
@ -123,9 +120,6 @@ export const entities = [
UserPublickey,
UserList,
UserListJoining,
UserGroup,
UserGroupJoining,
UserGroupInvitation,
UserNotePining,
UserSecurityKey,
UsedUsername,

View File

@ -21,8 +21,6 @@ export const kinds = [
"write:pages",
"write:page-likes",
"read:page-likes",
"read:user-groups",
"write:user-groups",
"read:gallery",
"write:gallery",
"read:gallery-likes",

View File

@ -1,7 +1,7 @@
import type {Antenna} from "@/models/entities/antenna.js";
import type {Note} from "@/models/entities/note.js";
import type {User} from "@/models/entities/user.js";
import {Blockings, UserGroupJoinings, UserListJoinings,} from "@/models/index.js";
import {Blockings, UserListJoinings,} from "@/models/index.js";
import {getFullApAccount} from "./convert-host.js";
import * as Acct from "@/misc/acct.js";
import {Cache} from "./cache.js";
@ -53,18 +53,6 @@ export async function checkHitAntenna(
).map((x) => x.userId);
if (!listUsers.includes(note.userId)) return false;
} else if (antenna.src === "group") {
const joining = await UserGroupJoinings.findOneByOrFail({
id: antenna.userGroupJoiningId!,
});
const groupUsers = (
await UserGroupJoinings.findBy({
userGroupId: joining.userGroupId,
})
).map((x) => x.userId);
if (!groupUsers.includes(note.userId)) return false;
} else if (antenna.src === "users") {
const accts = antenna.users.map((x) => {
const { username, host } = Acct.parse(x);

View File

@ -19,7 +19,6 @@ import {packedBlockingSchema} from "@/models/schema/blocking.js";
import {packedNoteReactionSchema} from "@/models/schema/note-reaction.js";
import {packedHashtagSchema} from "@/models/schema/hashtag.js";
import {packedPageSchema} from "@/models/schema/page.js";
import {packedUserGroupSchema} from "@/models/schema/user-group.js";
import {packedNoteFavoriteSchema} from "@/models/schema/note-favorite.js";
import {packedAntennaSchema} from "@/models/schema/antenna.js";
import {packedClipSchema} from "@/models/schema/clip.js";
@ -39,7 +38,6 @@ export const refs = {
User: packedUserSchema,
UserList: packedUserListSchema,
UserGroup: packedUserGroupSchema,
App: packedAppSchema,
NoteEdit: packedNoteEdit,
NoteReaction: packedNoteReactionSchema,

View File

@ -1,15 +1,7 @@
import {
PrimaryColumn,
Entity,
Index,
JoinColumn,
Column,
ManyToOne,
} from "typeorm";
import { User } from "./user.js";
import { id } from "../id.js";
import { UserList } from "./user-list.js";
import { UserGroupJoining } from "./user-group-joining.js";
import {Column, Entity, Index, JoinColumn, ManyToOne, PrimaryColumn,} from "typeorm";
import {User} from "./user.js";
import {id} from "../id.js";
import {UserList} from "./user-list.js";
@Entity()
export class Antenna {
@ -41,9 +33,9 @@ export class Antenna {
public name: string;
@Column("enum", {
enum: ["home", "all", "users", "list", "group", "instances"],
enum: ["home", "all", "users", "list", "instances"],
})
public src: "home" | "all" | "users" | "list" | "group" | "instances";
public src: "home" | "all" | "users" | "list" | "instances";
@Column({
...id(),
@ -57,18 +49,6 @@ export class Antenna {
@JoinColumn()
public userList: UserList | null;
@Column({
...id(),
nullable: true,
})
public userGroupJoiningId: UserGroupJoining["id"] | null;
@ManyToOne((type) => UserGroupJoining, {
onDelete: "CASCADE",
})
@JoinColumn()
public userGroupJoining: UserGroupJoining | null;
@Column("varchar", {
length: 1024,
array: true,

View File

@ -1,18 +1,10 @@
import {
Entity,
Index,
JoinColumn,
ManyToOne,
Column,
PrimaryColumn,
} from "typeorm";
import { User } from "./user.js";
import { id } from "../id.js";
import { Note } from "./note.js";
import { FollowRequest } from "./follow-request.js";
import { UserGroupInvitation } from "./user-group-invitation.js";
import { AccessToken } from "./access-token.js";
import { notificationTypes } from "@/types.js";
import {Column, Entity, Index, JoinColumn, ManyToOne, PrimaryColumn,} from "typeorm";
import {User} from "./user.js";
import {id} from "../id.js";
import {Note} from "./note.js";
import {FollowRequest} from "./follow-request.js";
import {AccessToken} from "./access-token.js";
import {notificationTypes} from "@/types.js";
@Entity()
export class Notification {
@ -70,7 +62,6 @@ export class Notification {
* pollEnded -
* receiveFollowRequest -
* followRequestAccepted - A follow request has been accepted.
* groupInvited -
* app - App notifications.
*/
@Index()
@ -114,18 +105,6 @@ export class Notification {
@JoinColumn()
public followRequest: FollowRequest | null;
@Column({
...id(),
nullable: true,
})
public userGroupInvitationId: UserGroupInvitation["id"] | null;
@ManyToOne((type) => UserGroupInvitation, {
onDelete: "CASCADE",
})
@JoinColumn()
public userGroupInvitation: UserGroupInvitation | null;
@Column("varchar", {
length: 128,
nullable: true,

View File

@ -1,49 +0,0 @@
import {
PrimaryColumn,
Entity,
Index,
JoinColumn,
Column,
ManyToOne,
} from "typeorm";
import { User } from "./user.js";
import { UserGroup } from "./user-group.js";
import { id } from "../id.js";
@Entity()
@Index(["userId", "userGroupId"], { unique: true })
export class UserGroupInvitation {
@PrimaryColumn(id())
public id: string;
@Column("timestamp with time zone", {
comment: "The created date of the UserGroupInvitation.",
})
public createdAt: Date;
@Index()
@Column({
...id(),
comment: "The user ID.",
})
public userId: User["id"];
@ManyToOne((type) => User, {
onDelete: "CASCADE",
})
@JoinColumn()
public user: User | null;
@Index()
@Column({
...id(),
comment: "The group ID.",
})
public userGroupId: UserGroup["id"];
@ManyToOne((type) => UserGroup, {
onDelete: "CASCADE",
})
@JoinColumn()
public userGroup: UserGroup | null;
}

View File

@ -1,49 +0,0 @@
import {
PrimaryColumn,
Entity,
Index,
JoinColumn,
Column,
ManyToOne,
} from "typeorm";
import { User } from "./user.js";
import { UserGroup } from "./user-group.js";
import { id } from "../id.js";
@Entity()
@Index(["userId", "userGroupId"], { unique: true })
export class UserGroupJoining {
@PrimaryColumn(id())
public id: string;
@Column("timestamp with time zone", {
comment: "The created date of the UserGroupJoining.",
})
public createdAt: Date;
@Index()
@Column({
...id(),
comment: "The user ID.",
})
public userId: User["id"];
@ManyToOne((type) => User, {
onDelete: "CASCADE",
})
@JoinColumn()
public user: User | null;
@Index()
@Column({
...id(),
comment: "The group ID.",
})
public userGroupId: UserGroup["id"];
@ManyToOne((type) => UserGroup, {
onDelete: "CASCADE",
})
@JoinColumn()
public userGroup: UserGroup | null;
}

View File

@ -1,53 +0,0 @@
import {
Entity,
Index,
JoinColumn,
Column,
PrimaryColumn,
ManyToOne,
} from "typeorm";
import { User } from "./user.js";
import { id } from "../id.js";
@Entity()
export class UserGroup {
@PrimaryColumn(id())
public id: string;
@Index()
@Column("timestamp with time zone", {
comment: "The created date of the UserGroup.",
})
public createdAt: Date;
@Column("varchar", {
length: 256,
})
public name: string;
@Index()
@Column({
...id(),
comment: "The ID of owner.",
})
public userId: User["id"];
@ManyToOne((type) => User, {
onDelete: "CASCADE",
})
@JoinColumn()
public user: User | null;
@Column("boolean", {
default: false,
})
public isPrivate: boolean;
constructor(data: Partial<UserGroup>) {
if (data == null) return;
for (const [k, v] of Object.entries(data)) {
(this as any)[k] = v;
}
}
}

View File

@ -78,7 +78,7 @@ export class UserProfile {
public emailVerified: boolean;
@Column("jsonb", {
default: ["follow", "receiveFollowRequest", "groupInvited"],
default: ["follow", "receiveFollowRequest"],
})
public emailNotificationTypes: string[];

View File

@ -19,9 +19,6 @@ import {UserNotePining} from "./entities/user-note-pining.js";
import {SigninRepository} from "./repositories/signin.js";
import {UserListRepository} from "./repositories/user-list.js";
import {UserListJoining} from "./entities/user-list-joining.js";
import {UserGroupRepository} from "./repositories/user-group.js";
import {UserGroupJoining} from "./entities/user-group-joining.js";
import {UserGroupInvitationRepository} from "./repositories/user-group-invitation.js";
import {FollowRequestRepository} from "./repositories/follow-request.js";
import {MutingRepository} from "./repositories/muting.js";
import {RenoteMutingRepository} from "./repositories/renote-muting.js";
@ -84,9 +81,6 @@ export const UserSecurityKeys = db.getRepository(UserSecurityKey);
export const UserPublickeys = db.getRepository(UserPublickey);
export const UserLists = UserListRepository;
export const UserListJoinings = db.getRepository(UserListJoining);
export const UserGroups = UserGroupRepository;
export const UserGroupJoinings = db.getRepository(UserGroupJoining);
export const UserGroupInvitations = UserGroupInvitationRepository;
export const UserNotePinings = db.getRepository(UserNotePining);
export const UserIps = db.getRepository(UserIp);
export const UsedUsernames = db.getRepository(UsedUsername);

View File

@ -1,7 +1,7 @@
import {db} from "@/db/postgre.js";
import {Antenna} from "@/models/entities/antenna.js";
import type {Packed} from "@/misc/schema.js";
import {AntennaNotes, UserGroupJoinings} from "../index.js";
import {AntennaNotes} from "../index.js";
export const AntennaRepository = db.getRepository(Antenna).extend({
async pack(src: Antenna["id"] | Antenna): Promise<Packed<"Antenna">> {
@ -11,9 +11,6 @@ export const AntennaRepository = db.getRepository(Antenna).extend({
const hasUnreadNote =
(await AntennaNotes.findOneBy({ antennaId: antenna.id, read: false })) !=
null;
const userGroupJoining = antenna.userGroupJoiningId
? await UserGroupJoinings.findOneBy({ id: antenna.userGroupJoiningId })
: null;
return {
id: antenna.id,
@ -23,7 +20,6 @@ export const AntennaRepository = db.getRepository(Antenna).extend({
excludeKeywords: antenna.excludeKeywords,
src: antenna.src,
userListId: antenna.userListId,
userGroupId: userGroupJoining ? userGroupJoining.userGroupId : null,
users: antenna.users,
instances: antenna.instances,
caseSensitive: antenna.caseSensitive,

View File

@ -7,7 +7,7 @@ import type {NoteReaction} from "@/models/entities/note-reaction.js";
import type {User} from "@/models/entities/user.js";
import {aggregateNoteEmojis, prefetchEmojis} from "@/misc/populate-emojis.js";
import {db} from "@/db/postgre.js";
import {AccessTokens, NoteReactions, UserGroupInvitations, Users,} from "../index.js";
import {AccessTokens, NoteReactions, Users,} from "../index.js";
import {getNote} from "@/server/api/common/getters.js";
export const NotificationRepository = db.getRepository(Notification).extend({
@ -76,13 +76,6 @@ export const NotificationRepository = db.getRepository(Notification).extend({
note: getNote(notification.noteId!, { id: notification.notifieeId }),
}
: {}),
...(notification.type === "groupInvited"
? {
invitation: UserGroupInvitations.pack(
notification.userGroupInvitationId!,
),
}
: {}),
...(notification.type === "app"
? {
body: notification.customBody,

View File

@ -1,23 +0,0 @@
import { db } from "@/db/postgre.js";
import { UserGroupInvitation } from "@/models/entities/user-group-invitation.js";
import { UserGroups } from "../index.js";
export const UserGroupInvitationRepository = db
.getRepository(UserGroupInvitation)
.extend({
async pack(src: UserGroupInvitation["id"] | UserGroupInvitation) {
const invitation =
typeof src === "object" ? src : await this.findOneByOrFail({ id: src });
return {
id: invitation.id,
group: await UserGroups.pack(
invitation.userGroup || invitation.userGroupId,
),
};
},
packMany(invitations: any[]) {
return Promise.all(invitations.map((x) => this.pack(x)));
},
});

View File

@ -1,23 +0,0 @@
import { db } from "@/db/postgre.js";
import { UserGroup } from "@/models/entities/user-group.js";
import { UserGroupJoinings } from "../index.js";
import type { Packed } from "@/misc/schema.js";
export const UserGroupRepository = db.getRepository(UserGroup).extend({
async pack(src: UserGroup["id"] | UserGroup): Promise<Packed<"UserGroup">> {
const userGroup =
typeof src === "object" ? src : await this.findOneByOrFail({ id: src });
const users = await UserGroupJoinings.findBy({
userGroupId: userGroup.id,
});
return {
id: userGroup.id,
createdAt: userGroup.createdAt.toISOString(),
name: userGroup.name,
ownerId: userGroup.userId,
userIds: users.map((x) => x.userId),
};
},
});

View File

@ -52,7 +52,7 @@ export const packedAntennaSchema = {
type: "string",
optional: false,
nullable: false,
enum: ["home", "all", "users", "list", "group", "instances"],
enum: ["home", "all", "users", "list", "instances"],
},
userListId: {
type: "string",
@ -60,12 +60,6 @@ export const packedAntennaSchema = {
nullable: true,
format: "id",
},
userGroupId: {
type: "string",
optional: false,
nullable: true,
format: "id",
},
users: {
type: "array",
optional: false,

View File

@ -1,40 +0,0 @@
export const packedUserGroupSchema = {
type: "object",
properties: {
id: {
type: "string",
optional: false,
nullable: false,
format: "id",
example: "xxxxxxxxxx",
},
createdAt: {
type: "string",
optional: false,
nullable: false,
format: "date-time",
},
name: {
type: "string",
optional: false,
nullable: false,
},
ownerId: {
type: "string",
nullable: false,
optional: false,
format: "id",
},
userIds: {
type: "array",
nullable: false,
optional: true,
items: {
type: "string",
nullable: false,
optional: false,
format: "id",
},
},
},
} as const;

View File

@ -203,7 +203,6 @@ import * as ep___i_signinHistory from "./endpoints/i/signin-history.js";
import * as ep___i_unpin from "./endpoints/i/unpin.js";
import * as ep___i_updateEmail from "./endpoints/i/update-email.js";
import * as ep___i_update from "./endpoints/i/update.js";
import * as ep___i_userGroupInvites from "./endpoints/i/user-group-invites.js";
import * as ep___i_webhooks_create from "./endpoints/i/webhooks/create.js";
import * as ep___i_webhooks_show from "./endpoints/i/webhooks/show.js";
import * as ep___i_webhooks_list from "./endpoints/i/webhooks/list.js";
@ -284,18 +283,6 @@ import * as ep___users_followers from "./endpoints/users/followers.js";
import * as ep___users_following from "./endpoints/users/following.js";
import * as ep___users_gallery_posts from "./endpoints/users/gallery/posts.js";
import * as ep___users_getFrequentlyRepliedUsers from "./endpoints/users/get-frequently-replied-users.js";
import * as ep___users_groups_create from "./endpoints/users/groups/create.js";
import * as ep___users_groups_delete from "./endpoints/users/groups/delete.js";
import * as ep___users_groups_invitations_accept from "./endpoints/users/groups/invitations/accept.js";
import * as ep___users_groups_invitations_reject from "./endpoints/users/groups/invitations/reject.js";
import * as ep___users_groups_invite from "./endpoints/users/groups/invite.js";
import * as ep___users_groups_joined from "./endpoints/users/groups/joined.js";
import * as ep___users_groups_leave from "./endpoints/users/groups/leave.js";
import * as ep___users_groups_owned from "./endpoints/users/groups/owned.js";
import * as ep___users_groups_pull from "./endpoints/users/groups/pull.js";
import * as ep___users_groups_show from "./endpoints/users/groups/show.js";
import * as ep___users_groups_transfer from "./endpoints/users/groups/transfer.js";
import * as ep___users_groups_update from "./endpoints/users/groups/update.js";
import * as ep___users_lists_create from "./endpoints/users/lists/create.js";
import * as ep___users_lists_delete from "./endpoints/users/lists/delete.js";
import * as ep___users_lists_delete_all from "./endpoints/users/lists/delete-all.js";
@ -532,7 +519,6 @@ const eps = [
["i/unpin", ep___i_unpin],
["i/update-email", ep___i_updateEmail],
["i/update", ep___i_update],
["i/user-group-invites", ep___i_userGroupInvites],
["i/webhooks/create", ep___i_webhooks_create],
["i/webhooks/list", ep___i_webhooks_list],
["i/webhooks/show", ep___i_webhooks_show],
@ -613,18 +599,6 @@ const eps = [
["users/following", ep___users_following],
["users/gallery/posts", ep___users_gallery_posts],
["users/get-frequently-replied-users", ep___users_getFrequentlyRepliedUsers],
["users/groups/create", ep___users_groups_create],
["users/groups/delete", ep___users_groups_delete],
["users/groups/invitations/accept", ep___users_groups_invitations_accept],
["users/groups/invitations/reject", ep___users_groups_invitations_reject],
["users/groups/invite", ep___users_groups_invite],
["users/groups/joined", ep___users_groups_joined],
["users/groups/leave", ep___users_groups_leave],
["users/groups/owned", ep___users_groups_owned],
["users/groups/pull", ep___users_groups_pull],
["users/groups/show", ep___users_groups_show],
["users/groups/transfer", ep___users_groups_transfer],
["users/groups/update", ep___users_groups_update],
["users/lists/create", ep___users_lists_create],
["users/lists/delete", ep___users_lists_delete],
["users/lists/delete-all", ep___users_lists_delete_all],

View File

@ -1,8 +1,8 @@
import define from "../../define.js";
import { genId } from "@/misc/gen-id.js";
import { Antennas, UserLists, UserGroupJoinings } from "@/models/index.js";
import { ApiError } from "../../error.js";
import { publishInternalEvent } from "@/services/stream.js";
import {genId} from "@/misc/gen-id.js";
import {Antennas, UserLists} from "@/models/index.js";
import {ApiError} from "../../error.js";
import {publishInternalEvent} from "@/services/stream.js";
export const meta = {
tags: ["antennas"],
@ -18,12 +18,6 @@ export const meta = {
id: "95063e93-a283-4b8b-9aa5-bcdb8df69a7f",
},
noSuchUserGroup: {
message: "No such user group.",
code: "NO_SUCH_USER_GROUP",
id: "aa3c0b9a-8cae-47c0-92ac-202ce5906682",
},
tooManyAntennas: {
message: "Too many antennas.",
code: "TOO_MANY_ANTENNAS",
@ -45,10 +39,9 @@ export const paramDef = {
name: { type: "string", minLength: 1, maxLength: 100 },
src: {
type: "string",
enum: ["home", "all", "users", "list", "group", "instances"],
enum: ["home", "all", "users", "list", "instances"],
},
userListId: { type: "string", format: "misskey:id", nullable: true },
userGroupId: { type: "string", format: "misskey:id", nullable: true },
keywords: {
type: "array",
items: {
@ -99,9 +92,7 @@ export const paramDef = {
} as const;
export default define(meta, paramDef, async (ps, user) => {
if (user.movedToUri != null) throw new ApiError(meta.errors.noSuchUserGroup);
let userList;
let userGroupJoining;
const antennas = await Antennas.findBy({
userId: user.id,
@ -119,15 +110,6 @@ export default define(meta, paramDef, async (ps, user) => {
if (userList == null) {
throw new ApiError(meta.errors.noSuchUserList);
}
} else if (ps.src === "group" && ps.userGroupId) {
userGroupJoining = await UserGroupJoinings.findOneBy({
userGroupId: ps.userGroupId,
userId: user.id,
});
if (userGroupJoining == null) {
throw new ApiError(meta.errors.noSuchUserGroup);
}
}
const antenna = await Antennas.insert({
@ -137,7 +119,6 @@ export default define(meta, paramDef, async (ps, user) => {
name: ps.name,
src: ps.src,
userListId: userList ? userList.id : null,
userGroupJoiningId: userGroupJoining ? userGroupJoining.id : null,
keywords: ps.keywords,
excludeKeywords: ps.excludeKeywords,
users: ps.users,

View File

@ -1,7 +1,7 @@
import define from "../../define.js";
import { ApiError } from "../../error.js";
import { Antennas, UserLists, UserGroupJoinings } from "@/models/index.js";
import { publishInternalEvent } from "@/services/stream.js";
import {ApiError} from "../../error.js";
import {Antennas, UserLists} from "@/models/index.js";
import {publishInternalEvent} from "@/services/stream.js";
export const meta = {
tags: ["antennas"],
@ -22,12 +22,6 @@ export const meta = {
code: "NO_SUCH_USER_LIST",
id: "1c6b35c9-943e-48c2-81e4-2844989407f7",
},
noSuchUserGroup: {
message: "No such user group.",
code: "NO_SUCH_USER_GROUP",
id: "109ed789-b6eb-456e-b8a9-6059d567d385",
},
},
res: {
@ -45,10 +39,9 @@ export const paramDef = {
name: { type: "string", minLength: 1, maxLength: 100 },
src: {
type: "string",
enum: ["home", "all", "users", "list", "group", "instances"],
enum: ["home", "all", "users", "list", "instances"],
},
userListId: { type: "string", format: "misskey:id", nullable: true },
userGroupId: { type: "string", format: "misskey:id", nullable: true },
keywords: {
type: "array",
items: {
@ -122,22 +115,12 @@ export default define(meta, paramDef, async (ps, user) => {
if (userList == null) {
throw new ApiError(meta.errors.noSuchUserList);
}
} else if (ps.src === "group" && ps.userGroupId) {
userGroupJoining = await UserGroupJoinings.findOneBy({
userGroupId: ps.userGroupId,
userId: user.id,
});
if (userGroupJoining == null) {
throw new ApiError(meta.errors.noSuchUserGroup);
}
}
await Antennas.update(antenna.id, {
name: ps.name,
src: ps.src,
userListId: userList ? userList.id : null,
userGroupJoiningId: userGroupJoining ? userGroupJoining.id : null,
keywords: ps.keywords,
excludeKeywords: ps.excludeKeywords,
users: ps.users,

View File

@ -1,60 +0,0 @@
import define from "../../define.js";
import { UserGroupInvitations } from "@/models/index.js";
import { makePaginationQuery } from "../../common/make-pagination-query.js";
export const meta = {
tags: ["account", "groups"],
requireCredential: true,
kind: "read:user-groups",
res: {
type: "array",
optional: false,
nullable: false,
items: {
type: "object",
optional: false,
nullable: false,
properties: {
id: {
type: "string",
optional: false,
nullable: false,
format: "id",
},
group: {
type: "object",
optional: false,
nullable: false,
ref: "UserGroup",
},
},
},
},
} as const;
export const paramDef = {
type: "object",
properties: {
limit: { type: "integer", minimum: 1, maximum: 100, default: 10 },
sinceId: { type: "string", format: "misskey:id" },
untilId: { type: "string", format: "misskey:id" },
},
required: [],
} as const;
export default define(meta, paramDef, async (ps, user) => {
const query = makePaginationQuery(
UserGroupInvitations.createQueryBuilder("invitation"),
ps.sinceId,
ps.untilId,
)
.andWhere("invitation.userId = :meId", { meId: user.id })
.leftJoinAndSelect("invitation.userGroup", "user_group");
const invitations = await query.take(ps.limit).getMany();
return await UserGroupInvitations.packMany(invitations);
});

View File

@ -1,49 +0,0 @@
import { UserGroups, UserGroupJoinings } from "@/models/index.js";
import { genId } from "@/misc/gen-id.js";
import type { UserGroup } from "@/models/entities/user-group.js";
import type { UserGroupJoining } from "@/models/entities/user-group-joining.js";
import define from "../../../define.js";
export const meta = {
tags: ["groups"],
requireCredential: true,
kind: "write:user-groups",
description: "Create a new group.",
res: {
type: "object",
optional: false,
nullable: false,
ref: "UserGroup",
},
} as const;
export const paramDef = {
type: "object",
properties: {
name: { type: "string", minLength: 1, maxLength: 100 },
},
required: ["name"],
} as const;
export default define(meta, paramDef, async (ps, user) => {
const userGroup = await UserGroups.insert({
id: genId(),
createdAt: new Date(),
userId: user.id,
name: ps.name,
} as UserGroup).then((x) => UserGroups.findOneByOrFail(x.identifiers[0]));
// Push the owner
await UserGroupJoinings.insert({
id: genId(),
createdAt: new Date(),
userId: user.id,
userGroupId: userGroup.id,
} as UserGroupJoining);
return await UserGroups.pack(userGroup);
});

View File

@ -1,42 +0,0 @@
import { UserGroups } from "@/models/index.js";
import define from "../../../define.js";
import { ApiError } from "../../../error.js";
export const meta = {
tags: ["groups"],
requireCredential: true,
kind: "write:user-groups",
description: "Delete an existing group.",
errors: {
noSuchGroup: {
message: "No such group.",
code: "NO_SUCH_GROUP",
id: "63dbd64c-cd77-413f-8e08-61781e210b38",
},
},
} as const;
export const paramDef = {
type: "object",
properties: {
groupId: { type: "string", format: "misskey:id" },
},
required: ["groupId"],
} as const;
export default define(meta, paramDef, async (ps, user) => {
const userGroup = await UserGroups.findOneBy({
id: ps.groupId,
userId: user.id,
});
if (userGroup == null) {
throw new ApiError(meta.errors.noSuchGroup);
}
await UserGroups.delete(userGroup.id);
});

View File

@ -1,56 +0,0 @@
import { UserGroupJoinings, UserGroupInvitations } from "@/models/index.js";
import { genId } from "@/misc/gen-id.js";
import type { UserGroupJoining } from "@/models/entities/user-group-joining.js";
import { ApiError } from "../../../../error.js";
import define from "../../../../define.js";
export const meta = {
tags: ["groups", "users"],
requireCredential: true,
kind: "write:user-groups",
description: "Join a group the authenticated user has been invited to.",
errors: {
noSuchInvitation: {
message: "No such invitation.",
code: "NO_SUCH_INVITATION",
id: "98c11eca-c890-4f42-9806-c8c8303ebb5e",
},
},
} as const;
export const paramDef = {
type: "object",
properties: {
invitationId: { type: "string", format: "misskey:id" },
},
required: ["invitationId"],
} as const;
export default define(meta, paramDef, async (ps, user) => {
// Fetch the invitation
const invitation = await UserGroupInvitations.findOneBy({
id: ps.invitationId,
});
if (invitation == null) {
throw new ApiError(meta.errors.noSuchInvitation);
}
if (invitation.userId !== user.id) {
throw new ApiError(meta.errors.noSuchInvitation);
}
// Push the user
await UserGroupJoinings.insert({
id: genId(),
createdAt: new Date(),
userId: user.id,
userGroupId: invitation.userGroupId,
} as UserGroupJoining);
UserGroupInvitations.delete(invitation.id);
});

View File

@ -1,47 +0,0 @@
import { UserGroupInvitations } from "@/models/index.js";
import define from "../../../../define.js";
import { ApiError } from "../../../../error.js";
export const meta = {
tags: ["groups", "users"],
requireCredential: true,
kind: "write:user-groups",
description:
"Delete an existing group invitation for the authenticated user without joining the group.",
errors: {
noSuchInvitation: {
message: "No such invitation.",
code: "NO_SUCH_INVITATION",
id: "ad7471d4-2cd9-44b4-ac68-e7136b4ce656",
},
},
} as const;
export const paramDef = {
type: "object",
properties: {
invitationId: { type: "string", format: "misskey:id" },
},
required: ["invitationId"],
} as const;
export default define(meta, paramDef, async (ps, user) => {
// Fetch the invitation
const invitation = await UserGroupInvitations.findOneBy({
id: ps.invitationId,
});
if (invitation == null) {
throw new ApiError(meta.errors.noSuchInvitation);
}
if (invitation.userId !== user.id) {
throw new ApiError(meta.errors.noSuchInvitation);
}
await UserGroupInvitations.delete(invitation.id);
});

View File

@ -1,108 +0,0 @@
import {
UserGroups,
UserGroupJoinings,
UserGroupInvitations,
} from "@/models/index.js";
import { genId } from "@/misc/gen-id.js";
import type { UserGroupInvitation } from "@/models/entities/user-group-invitation.js";
import { createNotification } from "@/services/create-notification.js";
import { getUser } from "../../../common/getters.js";
import { ApiError } from "../../../error.js";
import define from "../../../define.js";
export const meta = {
tags: ["groups", "users"],
requireCredential: true,
kind: "write:user-groups",
description: "Invite a user to an existing group.",
errors: {
noSuchGroup: {
message: "No such group.",
code: "NO_SUCH_GROUP",
id: "583f8bc0-8eee-4b78-9299-1e14fc91e409",
},
noSuchUser: {
message: "No such user.",
code: "NO_SUCH_USER",
id: "da52de61-002c-475b-90e1-ba64f9cf13a8",
},
alreadyAdded: {
message: "That user has already been added to that group.",
code: "ALREADY_ADDED",
id: "7e35c6a0-39b2-4488-aea6-6ee20bd5da2c",
},
alreadyInvited: {
message: "That user has already been invited to that group.",
code: "ALREADY_INVITED",
id: "ee0f58b4-b529-4d13-b761-b9a3e69f97e6",
},
},
} as const;
export const paramDef = {
type: "object",
properties: {
groupId: { type: "string", format: "misskey:id" },
userId: { type: "string", format: "misskey:id" },
},
required: ["groupId", "userId"],
} as const;
export default define(meta, paramDef, async (ps, me) => {
// Fetch the group
const userGroup = await UserGroups.findOneBy({
id: ps.groupId,
userId: me.id,
});
if (userGroup == null) {
throw new ApiError(meta.errors.noSuchGroup);
}
// Fetch the user
const user = await getUser(ps.userId).catch((e) => {
if (e.id === "15348ddd-432d-49c2-8a5a-8069753becff")
throw new ApiError(meta.errors.noSuchUser);
throw e;
});
const joining = await UserGroupJoinings.findOneBy({
userGroupId: userGroup.id,
userId: user.id,
});
if (joining) {
throw new ApiError(meta.errors.alreadyAdded);
}
const existInvitation = await UserGroupInvitations.findOneBy({
userGroupId: userGroup.id,
userId: user.id,
});
if (existInvitation) {
throw new ApiError(meta.errors.alreadyInvited);
}
const invitation = await UserGroupInvitations.insert({
id: genId(),
createdAt: new Date(),
userId: user.id,
userGroupId: userGroup.id,
} as UserGroupInvitation).then((x) =>
UserGroupInvitations.findOneByOrFail(x.identifiers[0]),
);
// 通知を作成
createNotification(user.id, "groupInvited", {
notifierId: me.id,
userGroupInvitationId: invitation.id,
});
});

View File

@ -1,48 +0,0 @@
import { Not, In } from "typeorm";
import { UserGroups, UserGroupJoinings } from "@/models/index.js";
import define from "../../../define.js";
export const meta = {
tags: ["groups", "account"],
requireCredential: true,
kind: "read:user-groups",
description: "List the groups that the authenticated user is a member of.",
res: {
type: "array",
optional: false,
nullable: false,
items: {
type: "object",
optional: false,
nullable: false,
ref: "UserGroup",
},
},
} as const;
export const paramDef = {
type: "object",
properties: {},
required: [],
} as const;
export default define(meta, paramDef, async (ps, me) => {
const ownedGroups = await UserGroups.findBy({
userId: me.id,
});
const joinings = await UserGroupJoinings.findBy({
userId: me.id,
...(ownedGroups.length > 0
? {
userGroupId: Not(In(ownedGroups.map((x) => x.id))),
}
: {}),
});
return await Promise.all(joinings.map((x) => UserGroups.pack(x.userGroupId)));
});

View File

@ -1,53 +0,0 @@
import { UserGroups, UserGroupJoinings } from "@/models/index.js";
import define from "../../../define.js";
import { ApiError } from "../../../error.js";
export const meta = {
tags: ["groups", "users"],
requireCredential: true,
kind: "write:user-groups",
description:
"Leave a group. The owner of a group can not leave. They must transfer ownership or delete the group instead.",
errors: {
noSuchGroup: {
message: "No such group.",
code: "NO_SUCH_GROUP",
id: "62780270-1f67-5dc0-daca-3eb510612e31",
},
youAreOwner: {
message: "Your are the owner.",
code: "YOU_ARE_OWNER",
id: "b6d6e0c2-ef8a-9bb8-653d-79f4a3107c69",
},
},
} as const;
export const paramDef = {
type: "object",
properties: {
groupId: { type: "string", format: "misskey:id" },
},
required: ["groupId"],
} as const;
export default define(meta, paramDef, async (ps, me) => {
// Fetch the group
const userGroup = await UserGroups.findOneBy({
id: ps.groupId,
});
if (userGroup == null) {
throw new ApiError(meta.errors.noSuchGroup);
}
if (me.id === userGroup.userId) {
throw new ApiError(meta.errors.youAreOwner);
}
await UserGroupJoinings.delete({ userGroupId: userGroup.id, userId: me.id });
});

View File

@ -1,38 +0,0 @@
import { UserGroups } from "@/models/index.js";
import define from "../../../define.js";
export const meta = {
tags: ["groups", "account"],
requireCredential: true,
kind: "read:user-groups",
description: "List the groups that the authenticated user is the owner of.",
res: {
type: "array",
optional: false,
nullable: false,
items: {
type: "object",
optional: false,
nullable: false,
ref: "UserGroup",
},
},
} as const;
export const paramDef = {
type: "object",
properties: {},
required: [],
} as const;
export default define(meta, paramDef, async (ps, me) => {
const userGroups = await UserGroups.findBy({
userId: me.id,
});
return await Promise.all(userGroups.map((x) => UserGroups.pack(x)));
});

View File

@ -1,73 +0,0 @@
import { UserGroups, UserGroupJoinings } from "@/models/index.js";
import define from "../../../define.js";
import { ApiError } from "../../../error.js";
import { getUser } from "../../../common/getters.js";
export const meta = {
tags: ["groups", "users"],
requireCredential: true,
kind: "write:user-groups",
description:
"Removes a specified user from a group. The owner can not be removed.",
errors: {
noSuchGroup: {
message: "No such group.",
code: "NO_SUCH_GROUP",
id: "4662487c-05b1-4b78-86e5-fd46998aba74",
},
noSuchUser: {
message: "No such user.",
code: "NO_SUCH_USER",
id: "0b5cc374-3681-41da-861e-8bc1146f7a55",
},
isOwner: {
message: "The user is the owner.",
code: "IS_OWNER",
id: "1546eed5-4414-4dea-81c1-b0aec4f6d2af",
},
},
} as const;
export const paramDef = {
type: "object",
properties: {
groupId: { type: "string", format: "misskey:id" },
userId: { type: "string", format: "misskey:id" },
},
required: ["groupId", "userId"],
} as const;
export default define(meta, paramDef, async (ps, me) => {
// Fetch the group
const userGroup = await UserGroups.findOneBy({
id: ps.groupId,
userId: me.id,
});
if (userGroup == null) {
throw new ApiError(meta.errors.noSuchGroup);
}
// Fetch the user
const user = await getUser(ps.userId).catch((e) => {
if (e.id === "15348ddd-432d-49c2-8a5a-8069753becff")
throw new ApiError(meta.errors.noSuchUser);
throw e;
});
if (user.id === userGroup.userId) {
throw new ApiError(meta.errors.isOwner);
}
// Pull the user
await UserGroupJoinings.delete({
userGroupId: userGroup.id,
userId: user.id,
});
});

View File

@ -1,58 +0,0 @@
import { UserGroups, UserGroupJoinings } from "@/models/index.js";
import define from "../../../define.js";
import { ApiError } from "../../../error.js";
export const meta = {
tags: ["groups", "account"],
requireCredential: true,
kind: "read:user-groups",
description: "Show the properties of a group.",
res: {
type: "object",
optional: false,
nullable: false,
ref: "UserGroup",
},
errors: {
noSuchGroup: {
message: "No such group.",
code: "NO_SUCH_GROUP",
id: "ea04751e-9b7e-487b-a509-330fb6bd6b9b",
},
},
} as const;
export const paramDef = {
type: "object",
properties: {
groupId: { type: "string", format: "misskey:id" },
},
required: ["groupId"],
} as const;
export default define(meta, paramDef, async (ps, me) => {
// Fetch the group
const userGroup = await UserGroups.findOneBy({
id: ps.groupId,
});
if (userGroup == null) {
throw new ApiError(meta.errors.noSuchGroup);
}
const joining = await UserGroupJoinings.findOneBy({
userId: me.id,
userGroupId: userGroup.id,
});
if (joining == null && userGroup.userId !== me.id) {
throw new ApiError(meta.errors.noSuchGroup);
}
return await UserGroups.pack(userGroup);
});

View File

@ -1,85 +0,0 @@
import { UserGroups, UserGroupJoinings } from "@/models/index.js";
import define from "../../../define.js";
import { ApiError } from "../../../error.js";
import { getUser } from "../../../common/getters.js";
export const meta = {
tags: ["groups", "users"],
requireCredential: true,
kind: "write:user-groups",
description:
"Transfer ownership of a group from the authenticated user to another user.",
res: {
type: "object",
optional: false,
nullable: false,
ref: "UserGroup",
},
errors: {
noSuchGroup: {
message: "No such group.",
code: "NO_SUCH_GROUP",
id: "8e31d36b-2f88-4ccd-a438-e2d78a9162db",
},
noSuchUser: {
message: "No such user.",
code: "NO_SUCH_USER",
id: "711f7ebb-bbb9-4dfa-b540-b27809fed5e9",
},
noSuchGroupMember: {
message: "No such group member.",
code: "NO_SUCH_GROUP_MEMBER",
id: "d31bebee-196d-42c2-9a3e-9474d4be6cc4",
},
},
} as const;
export const paramDef = {
type: "object",
properties: {
groupId: { type: "string", format: "misskey:id" },
userId: { type: "string", format: "misskey:id" },
},
required: ["groupId", "userId"],
} as const;
export default define(meta, paramDef, async (ps, me) => {
// Fetch the group
const userGroup = await UserGroups.findOneBy({
id: ps.groupId,
userId: me.id,
});
if (userGroup == null) {
throw new ApiError(meta.errors.noSuchGroup);
}
// Fetch the user
const user = await getUser(ps.userId).catch((e) => {
if (e.id === "15348ddd-432d-49c2-8a5a-8069753becff")
throw new ApiError(meta.errors.noSuchUser);
throw e;
});
const joining = await UserGroupJoinings.findOneBy({
userGroupId: userGroup.id,
userId: user.id,
});
if (joining == null) {
throw new ApiError(meta.errors.noSuchGroupMember);
}
await UserGroups.update(userGroup.id, {
userId: ps.userId,
});
return await UserGroups.pack(userGroup.id);
});

View File

@ -1,55 +0,0 @@
import { UserGroups } from "@/models/index.js";
import define from "../../../define.js";
import { ApiError } from "../../../error.js";
export const meta = {
tags: ["groups"],
requireCredential: true,
kind: "write:user-groups",
description: "Update the properties of a group.",
res: {
type: "object",
optional: false,
nullable: false,
ref: "UserGroup",
},
errors: {
noSuchGroup: {
message: "No such group.",
code: "NO_SUCH_GROUP",
id: "9081cda3-7a9e-4fac-a6ce-908d70f282f6",
},
},
} as const;
export const paramDef = {
type: "object",
properties: {
groupId: { type: "string", format: "misskey:id" },
name: { type: "string", minLength: 1, maxLength: 100 },
},
required: ["groupId", "name"],
} as const;
export default define(meta, paramDef, async (ps, me) => {
// Fetch the group
const userGroup = await UserGroups.findOneBy({
id: ps.groupId,
userId: me.id,
});
if (userGroup == null) {
throw new ApiError(meta.errors.noSuchGroup);
}
await UserGroups.update(userGroup.id, {
name: ps.name,
});
return await UserGroups.pack(userGroup.id);
});

View File

@ -9,7 +9,6 @@ export const notificationTypes = [
"pollEnded",
"receiveFollowRequest",
"followRequestAccepted",
"groupInvited",
"app",
] as const;