-
Notifications
You must be signed in to change notification settings - Fork 51
Event point system #430
base: staging
Are you sure you want to change the base?
Event point system #430
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks very good. I had a few comments.
selector := database.QuerySelector{ | ||
"id": id, | ||
"code": code, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am wondering why the selector was changed from id
to code
?
correct me if I'm wrong, but since we are trying to update the code
of the event, and you are also searching the database for an event with the new code
instead of the old code
(or ideally, the unique id
), it won't find the correct event.
The old code worked because we grabbed the event ID from PUT /event/code/{id} but since you removed that, I feel we are missing some information that is necessary to do this database update
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok so, I understand the issue at hand, but with the current setup, the table will have multiple fields where id
can be equal (since events can have a virtual and an in-person code). The idea behind switching the primary key to code
is to fix this unique identifier issue.
What I'm realizing now is that while the current POST
route works perfectly for updating information for id
, isVirtual
, and expiration
, we can't change code
without deleting the old one and creating a new one. A potential solution could be to make the route POST /event/code/{old_code_id}
. That way we can uniquely identify which code to modify and have the ability to modify the code id.
Also, for clarity in the model, I'll probably change the EventCode
struct to:
type EventCode struct {
CodeID string `json:"codeID"`
EventID string `json:"eventID"`
IsVirtual bool `json:"isVirtual"`
Expiration int64 `json:"expiration"`
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I think using {old_code} is a great way to fix it. I think we have two options.
- Change the endpoint to POST /event/code/{old_code_id} so we can update the correct object
- Don't allow API users to modify the code at all
I think 2 is a feasible option because once the random code is generated once, I don't see many reasons to change it afterwards.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright then. In both cases, would it be good to also have a DELETE route? Right now, the only way a code gets deleted is if its expiration datetime exceeds the current time and some user tries to utilize said code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes that would probably be good to have, but not necessary for this PR in my opinion
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alrighty, went ahead and implemented option 2. Also added a little note POST /event/code
in the docs saying that codes can't be updated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should state this explicitly though, in an explicit error message, and a note in the documentation.
As of right now, it's impossible to determine if the user is attempting to change code
. Since the method is essentially upserting, if the code simply doesn't exist, it creates a new row.
A possible solution might be to do something like POST /event/code/{code}
, but I feel then it would be a bit counterintuitive to not implement option 1.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is possible to prevent the user from changing the event struct's code
here.
After creating the selector, you can use findOne
to get the old event, then set the new eventCode
struct's code
field to that, and then finally do the upsert.
Here is a rough idea of what I was thinking
selector := database.QuerySelector{
"codeid": code,
}
// load the old code
var oldEventCode models.EventCode
err := db.FindOne("eventcodes", selector, &oldEventCode)
// update the code field to make sure it is not changed by the user
eventCode.code = oldEventCode.code
// then do the upsert as normal
_, err := db.Upsert("eventcodes", selector, &eventCode)
You can wrap the findOne
in an if-statement. If the eventCode does not already exist, you can run the upsert directly
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
selector := database.QuerySelector{ "codeid": code, }
Is this assuming that the code
variable is the old code? That would be implementing option 1), right?
In my opinion, I think it is alright to create a new row if a new code is specified. Putting the responsibility of calling this endpoint with the correct code can be placed on the caller, instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is possible to prevent the user from changing the event struct's
code
here.After creating the selector, you can use
findOne
to get the old event, then set the neweventCode
struct'scode
field to that, and then finally do the upsert.Here is a rough idea of what I was thinking
selector := database.QuerySelector{ "codeid": code, } // load the old code var oldEventCode models.EventCode err := db.FindOne("eventcodes", selector, &oldEventCode) // update the code field to make sure it is not changed by the user eventCode.code = oldEventCode.code // then do the upsert as normal _, err := db.Upsert("eventcodes", selector, &eventCode)You can wrap the
findOne
in an if-statement. If the eventCode does not already exist, you can run the upsert directly
The current implementation works perfectly fine. In all cases when something is being upserted, it will either be updated if code
is found or inserted otherwise.
For clarification on what I said, I was building on what Yong commented on; if we were to return some error to the user saying that they are modifying the code, we would probably need something like POST /event/code/{old_code}
. It's rather a small nit really since it should be clear that the code can't be changed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, left some nits
selector := database.QuerySelector{ | ||
"id": id, | ||
"code": code, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with Matas on not letting users to modify the code id. We should state this explicitly though, in an explicit error message, and a note in the documentation.
"teamStatus": "LOOKING_FOR_TEAM", | ||
"description": "Lorem Ipsum…", | ||
"interests": ["C++", "Machine Learning"] | ||
"isVirtual": false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to add back the avatar URL, so we can randomly generate a profile picture and affix it to the profile.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we can randomly generate a profile picture and affix it to the profile
So, are we setting this to some URL on profile creation?
InPersonPoints
,InPersonVirtPoints
, andVirtualPoints
IsVirtual
to distinguish between code for virtual/in-person usePUT /event/code/{id}
toPOST /event/code/
GET /profile/user/{id}/
so that we can determine if the user redeeming the event is virtual or in-personprofileattendance
were resulting in duplicate rows with emptyid
fieldsPOST /event/checkin
to check the user for virtual status