Skip to content

Commit

Permalink
Clean up the ORM interface a little bit (#66)
Browse files Browse the repository at this point in the history
Change to use ctx everywhere.
  (Changing the transaction boundaries can occur later.)
  • Loading branch information
chuck-dbos authored Oct 12, 2023
1 parent 7f83403 commit dc0f02e
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 39 deletions.
56 changes: 29 additions & 27 deletions yky-social/src/Operations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,15 @@ async function comparePasswords(password: string, hashedPassword: string): Promi
return isMatch;
}

type ORMTC = TransactionContext<EntityManager>;

@DefaultRequiredRole(['user'])
export class Operations
{

@OperonTransaction()
@RequiredRole([])
static async createUser(ctx: TransactionContext<EntityManager>, first:string, last:string, uname:string, @SkipLogging pass:string) :
static async createUser(ctx: ORMTC, first:string, last:string, uname:string, @SkipLogging pass:string) :
Promise<UserLogin>
{
const manager = ctx.client;
Expand Down Expand Up @@ -88,10 +90,10 @@ static async createUser(ctx: TransactionContext<EntityManager>, first:string, la
return await manager.save(user);
}

static async logInUser(manager:EntityManager, uname:string, pass:string) :
static async logInUser(ctx: ORMTC, uname:string, pass:string) :
Promise<UserLogin>
{
const userRep = manager.getRepository(UserLogin);
const userRep = ctx.client.getRepository(UserLogin);
const existingUser = await userRep.findOneBy({
user_name: uname,
});
Expand All @@ -102,10 +104,10 @@ static async logInUser(manager:EntityManager, uname:string, pass:string) :
return existingUser;
}

static async logInUserId(manager:EntityManager, uname:string, pass:string) :
static async logInUserId(ctx: ORMTC, uname:string, pass:string) :
Promise<string>
{
const userRep = manager.getRepository(UserLogin);
const userRep = ctx.client.getRepository(UserLogin);
const existingUser = await userRep.findOneBy({
user_name: uname,
});
Expand All @@ -116,16 +118,16 @@ static async logInUserId(manager:EntityManager, uname:string, pass:string) :
return existingUser.id;
}

static async getMyProfile(manager:EntityManager, curUid:string) :
static async getMyProfile(ctx: ORMTC, curUid:string) :
Promise<UserProfile | null>
{
const upRep = manager.getRepository(UserProfile);
const upRep = ctx.client.getRepository(UserProfile);
return upRep.findOneBy({id: curUid});
}

@OperonTransaction({readOnly: true})
@RequiredRole([])
static async getMyProfilePhotoKey(ctx: TransactionContext<EntityManager>, curUid:string) :
static async getMyProfilePhotoKey(ctx: ORMTC, curUid:string) :
Promise<string | null>
{
const mRep = ctx.client.getRepository(MediaItem);
Expand All @@ -139,10 +141,10 @@ static async getMyProfilePhotoKey(ctx: TransactionContext<EntityManager>, curUid
return mi.media_url;
}

static async getPost(manager:EntityManager, _curUid: string, post:string) :
static async getPost(ctx: ORMTC, _curUid: string, post:string) :
Promise<Post | null>
{
const pRep = manager.getRepository(Post);
const pRep = ctx.client.getRepository(Post);
const res = pRep.findOne({
where: {id: post},
relations: {
Expand All @@ -154,7 +156,7 @@ static async getPost(manager:EntityManager, _curUid: string, post:string) :
//
// Returns other user's login, profile (if requested), our listing for his status, and his for us
@OperonTransaction({readOnly: true})
static async findUser(ctx: TransactionContext<EntityManager>, curUid:string, uname:string, getProfile:boolean, getStatus: boolean) :
static async findUser(ctx: ORMTC, curUid:string, uname:string, getProfile:boolean, getStatus: boolean) :
Promise<[UserLogin?, UserProfile?, GraphType?, GraphType?]>
{
const manager = ctx.client;
Expand Down Expand Up @@ -205,10 +207,10 @@ static async findUser(ctx: TransactionContext<EntityManager>, curUid:string, una
return [otherUser, profile, sgtype, tgtype];
}

static async getGraphStatus(manager: EntityManager, curUid : string, otherUid : string)
static async getGraphStatus(ctx: ORMTC, curUid : string, otherUid : string)
: Promise<GraphType>
{
const sgRep = manager.getRepository(SocialGraph);
const sgRep = ctx.client.getRepository(SocialGraph);
const rGraph = await sgRep.findOneBy({
src_id: curUid, tgt_id: otherUid
});
Expand All @@ -220,10 +222,10 @@ static async getGraphStatus(manager: EntityManager, curUid : string, otherUid :
}

// Set graph status
static async setGraphStatus(manager: EntityManager, curUid : string, otherUid : string, status : GraphType)
static async setGraphStatus(ctx: ORMTC, curUid : string, otherUid : string, status : GraphType)
: Promise<void>
{
const sgRep = manager.getRepository(SocialGraph);
const sgRep = ctx.client.getRepository(SocialGraph);
const ug = new SocialGraph();
ug.link_type = status;
ug.src_id = curUid;
Expand All @@ -239,7 +241,7 @@ static async setGraphStatus(manager: EntityManager, curUid : string, otherUid :

// Compose a post
@OperonTransaction()
static async makePost(ctx: TransactionContext<EntityManager>, txt : string)
static async makePost(ctx: ORMTC, txt : string)
{
const manager = ctx.client;

Expand Down Expand Up @@ -273,7 +275,7 @@ static async makePost(ctx: TransactionContext<EntityManager>, txt : string)

// Send a post
@OperonTransaction()
static async distributePost(ctx: TransactionContext<EntityManager>, p: Post) {
static async distributePost(ctx: ORMTC, p: Post) {
const manager = ctx.client;

// Deliver post to followers - TODO cross shard; TODO block list
Expand All @@ -300,7 +302,7 @@ static async distributePost(ctx: TransactionContext<EntityManager>, p: Post) {
}

// TODO: Deliver a post
static async makePM(manager: EntityManager, curUid : string, toUid : string, txt : string) :
static async makePM(ctx: ORMTC, curUid : string, toUid : string, txt : string) :
Promise<void>
{
// Create post
Expand All @@ -313,7 +315,7 @@ static async makePM(manager: EntityManager, curUid : string, toUid : string, txt
p.post_time = new Date();
p.post_type = PostType.PM;

const postRep = manager.getRepository(Post);
const postRep = ctx.client.getRepository(Post);
await postRep.insert(p);

// TODO: Decompose to allow media upload
Expand All @@ -326,11 +328,11 @@ static async makePM(manager: EntityManager, curUid : string, toUid : string, txt
st.send_date = p.post_time;
st.user_id = curUid;

const sendRep = manager.getRepository(TimelineSend);
const sendRep = ctx.client.getRepository(TimelineSend);
await sendRep.insert(st);

// Deliver post to recipient - TODO cross shard; TODO block list
const recvRep = manager.getRepository(TimelineRecv);
const recvRep = ctx.client.getRepository(TimelineRecv);
const rt = new TimelineRecv();
rt.post = p;
rt.post_id = p.id;
Expand All @@ -344,11 +346,11 @@ static async makePM(manager: EntityManager, curUid : string, toUid : string, txt
}

// Read a send timeline
static async readSendTimeline(manager: EntityManager, _curUser : string, timelineUser : string, type : SendType[], getPosts : boolean)
static async readSendTimeline(ctx: ORMTC, _curUser : string, timelineUser : string, type : SendType[], getPosts : boolean)
: Promise<TimelineSend []>
{
// TODO: Permissions
const tsRep = manager.getRepository(TimelineSend);
const tsRep = ctx.client.getRepository(TimelineSend);
return tsRep.find({
where: {
user_id: timelineUser,
Expand All @@ -365,10 +367,10 @@ static async readSendTimeline(manager: EntityManager, _curUser : string, timelin

// TODO: Read a recv timeline
// TODO: other filters
static async readRecvTimeline(manager: EntityManager, curUser : string, type : RecvType[], getPosts : boolean)
static async readRecvTimeline(ctx: ORMTC, curUser : string, type : RecvType[], getPosts : boolean)
: Promise<TimelineRecv []>
{
const trRep = manager.getRepository(TimelineRecv);
const trRep = ctx.client.getRepository(TimelineRecv);
return trRep.find({
where: {
user_id: curUser,
Expand Down Expand Up @@ -428,7 +430,7 @@ static async ensureS3FileDropped(ctx: OperonContext, key: string, bucket: string
}

@OperonTransaction()
static async writeMediaPost(ctx: TransactionContext<EntityManager>, mid: string, mkey: string) {
static async writeMediaPost(ctx: ORMTC, mid: string, mkey: string) {
const m = new MediaItem();
m.media_url = mkey;
m.media_id = mid;
Expand All @@ -440,7 +442,7 @@ static async writeMediaPost(ctx: TransactionContext<EntityManager>, mid: string,
}

@OperonTransaction()
static async writeMediaProfilePhoto(ctx: TransactionContext<EntityManager>, mid: string, mkey: string) {
static async writeMediaProfilePhoto(ctx: ORMTC, mid: string, mkey: string) {
const m = new MediaItem();
m.media_url = mkey;
m.media_id = mid;
Expand Down
18 changes: 6 additions & 12 deletions yky-social/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,7 @@ export class YKY
@GetApi('/recvtimeline')
static async receiveTimeline(ctx: TransactionContext<EntityManager>)
{
const manager = ctx.client;

const rtl = await Operations.readRecvTimeline(manager, ctx.authenticatedUser, [RecvType.POST], true); // TODO #4 - Integrate typeORM into transaction context
const rtl = await Operations.readRecvTimeline(ctx, ctx.authenticatedUser, [RecvType.POST], true);
const tl = rtl.map((tle) => {
return {postId: tle.post_id, fromUserId:tle.from_user_id, unread:tle.unread, sendDate: tle.send_date, recvType:tle.recv_type,
postText: tle.post?.text, postMentions: tle.post?.mentions};
Expand All @@ -115,9 +113,8 @@ export class YKY
{
// TODO: User id and modes
const userid = ctx.authenticatedUser;
const manager = ctx.client;

const rtl = await Operations.readSendTimeline(manager, userid, userid, [SendType.PM, SendType.POST, SendType.REPOST], true);
const rtl = await Operations.readSendTimeline(ctx, userid, userid, [SendType.PM, SendType.POST, SendType.REPOST], true);
const tl = rtl.map((tle) => {
return {postId: tle.post_id, fromUserId:tle.user_id, sendDate: tle.send_date, sendType:tle.send_type,
postText: tle.post?.text, postMentions: tle.post?.mentions};
Expand All @@ -143,8 +140,7 @@ export class YKY
static async getPost(ctx: TransactionContext<EntityManager>, @ArgRequired @ArgSource(ArgSources.URL) id: string) {
// TODO Validate user permissions

const manager = ctx.client;
const post = await Operations.getPost(manager, ctx.authenticatedUser, id);
const post = await Operations.getPost(ctx, ctx.authenticatedUser, id);
if (post) {
return { message: 'Retrieved.', post:post };
} else {
Expand All @@ -156,8 +152,7 @@ export class YKY
@PostApi("/login")
@RequiredRole([]) // Don't need any roles to log in
static async doLogin(ctx: TransactionContext<EntityManager>, @ArgRequired username: string, @ArgRequired @LogMask(LogMasks.HASH) password: string) {
const manager = ctx.client;
const user = await Operations.logInUser(manager, username, password);
const user = await Operations.logInUser(ctx, username, password);
return { message: 'Successful login.', id:user.id };
}

Expand All @@ -181,9 +176,8 @@ export class YKY
@OperonTransaction()
@PostApi("/follow")
static async doFollow(ctx: TransactionContext<EntityManager>, followUid: string) {
const manager = ctx.client;
const curStatus = await Operations.getGraphStatus(manager, ctx.authenticatedUser, followUid);
await Operations.setGraphStatus(manager, ctx.authenticatedUser, followUid, curStatus == GraphType.FRIEND ? GraphType.FOLLOW_FRIEND : GraphType.FOLLOW);
const curStatus = await Operations.getGraphStatus(ctx, ctx.authenticatedUser, followUid);
await Operations.setGraphStatus(ctx, ctx.authenticatedUser, followUid, curStatus == GraphType.FRIEND ? GraphType.FOLLOW_FRIEND : GraphType.FOLLOW);
// TODO: That UID wasn't validated - maybe the DB should validate it

return {message: "Followed."};
Expand Down

0 comments on commit dc0f02e

Please sign in to comment.