Skip to content

Commit

Permalink
Merge pull request #43 from badging/event-badging-table
Browse files Browse the repository at this point in the history
API routes for event badging
  • Loading branch information
kaxada committed Apr 8, 2024
2 parents 6fd8dbf + f79a6f1 commit e576c7e
Show file tree
Hide file tree
Showing 13 changed files with 258 additions and 34 deletions.
50 changes: 27 additions & 23 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Configure MySQL and make sure it is running on your machine before you proceed w

1. You'll need to [create a GitHub OAuth App](https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/creating-an-oauth-app) on your personal GitHub account. Creating a GitHub OAuth App will automatically generate a `Client_ID` and will also enable you to generate a `Client_Secret` for your OAuth App. Store these values safely because they will be needed while generating a `.env` file for the first time.

2. Create your personal [Augur Application](https://projectbadge.chaoss.io/account/settings?section=application) in order to generate an 'augur_client_secret'. Following the link, you will click on "register" and then fill in a couple of fields as required which will set up an account which you will log into. Click on your username(the one you filled in for the "user ID") at the top left and select "profile" which will take you to account settings. Under the account settings, in the left sidebar, click on "applications" and create a new application by entering an App name and a Redirect URL which will generate the `augur_client_secret` which will be listed in the last column of **_Your Apps_** table. Store the `augur_client_secret` together with the above GitHub OAuth credentials since it will be needed too while generating a `.env` file for the first time. The `augur_client_secret` which is the `AUGUR_CLIENT_SECRET` key is used to connect to the Augur API to submit repositories to the Augur Library for further badging.
2. Create your personal [Augur Application](https://projectbadge.chaoss.io/account/settings?section=application) in order to generate an 'augur*client_secret'. Following the link, you will click on "register" and then fill in a couple of fields as required which will set up an account which you will log into. Click on your username(the one you filled in for the "user ID") at the top left and select "profile" which will take you to account settings. Under the account settings, in the left sidebar, click on "applications" and create a new application by entering an App name and a Redirect URL which will generate the `augur_client_secret` which will be listed in the last column of \*\*\_Your Apps*\*\* table. Store the `augur_client_secret` together with the above GitHub OAuth credentials since it will be needed too while generating a `.env` file for the first time. The `augur_client_secret` which is the `AUGUR_CLIENT_SECRET` key is used to connect to the Augur API to submit repositories to the Augur Library for further badging.

After generating those values,

Expand All @@ -57,7 +57,7 @@ After generating those values,
npm install # installs packages and dependencies
```

2. **Make sure project is running**: This starts a *.env* configuration process if the *.env* file is missing.
2. **Make sure project is running**: This starts a _.env_ configuration process if the _.env_ file is missing.

```bash
npm run dev # this command will trigger a series of configuration questions in order setup your environmental variables
Expand Down Expand Up @@ -98,39 +98,43 @@ BadgingAPI follows a specific code style and coding standards. Please make sure

- **Variables and functions**: camelCase

````markdown
myVariable = 10;

function exampleFunction() {
return "Hello, World!"
};
```markdown
myVariable = 10;
function exampleFunction() {
return "Hello, World!"
};
```

- **Classes and constructors**: PascalCase

````markdown
class MyClass {
constructor(value) {
this.value = value;
}
};
```markdown
class MyClass {
constructor(value) {
this.value = value;
}
};
```

- **Filenames, constants, and environment variables**: Snake_case

````markdown
my_file_name.txt
```markdown
my_file_name.txt
const MAX_ATTEMPTS = 5;
const MAX_ATTEMPTS = 5;
DATABASE_URL = "localhost:3000"
DATABASE_URL = "localhost:3000"
```

- **HTML attributes and CSS class names**: Kebab-case

````markdown
<div class="my-element"></div>
```markdown
<div class="my-element"></div>
.my-element {
color: red;
};
.my-element {
color: red;
};
```

### Issue Tracking

Expand Down
49 changes: 49 additions & 0 deletions database/controllers/event.controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
const Event = require("../models/event.model");

const createEvent = async (event) => {
try {
const { event_name, event_URL, badge, reviewers, application } = event;

const newEvent = await Event.create({
event_name,
event_URL,
badge,
reviewers,
application,
});

console.log(`Event ${newEvent.event_name} created successfully`);
} catch (error) {
console.error(error);
}
};

// Get all Events
const getAllEvents = async (req, res) => {
try {
const events = await Event.findAll();
res.status(200).json(events);
} catch (error) {
res.status(500).json({ error: error.message });
}
};

// Get event by ID
const getEventById = async (req, res) => {
const { id } = req.params;
try {
const event = await Event.findByPk(id);
if (!event) {
return res.status(404).json({ message: "Event not found" });
}
res.status(200).json(event);
} catch (error) {
res.status(500).json({ error: error.message });
}
};

module.exports = {
createEvent,
getAllEvents,
getEventById,
};
59 changes: 59 additions & 0 deletions database/models/event.model.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
const { DataTypes } = require("sequelize");
const sequelize = require("../helpers/sequelize");

const Event = sequelize.define("events", {
date: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
allowNull: false,
},
event_name: {
type: DataTypes.STRING,
allowNull: false,
},
event_URL: {
type: DataTypes.STRING,
allowNull: false,
},
badge: {
type: DataTypes.JSON,
allowNull: false,
},
reviewers: {
type: DataTypes.JSON,
allowNull: false,
validate: {
isValidReviewers(value) {
if (!Array.isArray(value)) {
throw new Error("Reviewers must be an array.");
}
for (const reviewer of value) {
if (typeof reviewer.name !== "string" || reviewer.name.length > 255) {
throw new Error(
"Reviewer name must be a string with max length 255."
);
}
if (!isValidURL(reviewer.github_profile_link)) {
throw new Error("Invalid GitHub profile link format.");
}
}
},
},
},
application: {
type: DataTypes.JSON,
allowNull: false,
},
});

// Helper function to validate URL format
function isValidURL(url) {
try {
new URL(url);
return true;
} catch (error) {
return false;
}
}

module.exports = Event;
2 changes: 2 additions & 0 deletions event_badging/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const {
endReview,
assignChecklist,
updateReadme,
saveEvent,
} = require("./logic/index.js");

const eventBadging = async (name, octokit, payload) => {
Expand Down Expand Up @@ -35,6 +36,7 @@ const eventBadging = async (name, octokit, payload) => {

// when issue is closed, update the readme with the event
if (name === "issues" && payload.action === "closed") {
saveEvent(octokit, payload);
updateReadme(octokit, payload);
}
} else if (
Expand Down
3 changes: 2 additions & 1 deletion event_badging/logic/calculate.badge.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,8 @@ const calculateBadge = async (octokit, payload) => {
htmlBadgeImage: htmlBadgeImage,
reviewResult: reviewResult,
reviewerCount: reviewerCount,
assignedBadge: badgeAssigned[0],
assigned_badge: badgeAssigned[0],
badge_URL: url,
};

return messageObj;
Expand Down
2 changes: 2 additions & 0 deletions event_badging/logic/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ const help = require("./help");
const welcome = require("./welcome");
const assignChecklist = require("./assignChecklist");
const updateReadme = require("./updateReadme");
const saveEvent = require("./saveEvent");

module.exports = {
welcome,
help,
getResults,
endReview,
assignChecklist,
saveEvent,
updateReadme,
};
68 changes: 68 additions & 0 deletions event_badging/logic/saveEvent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
const { createEvent } = require("../../database/controllers/event.controller");
const calculateBadge = require("./calculate.badge.js");

const saveEvent = async (octokit, payload) => {
let { assigned_badge, badge_URL } = await calculateBadge(octokit, payload); // get badge name

const event_name = payload.issue.title.replace(/\[(.*?)\] /gi, "");
let event_URL;
if (payload.issue.title.includes("[Virtual Event]")) {
event_URL = await payload.issue.body
.slice(
payload.issue.body.indexOf("- Link to the Event Website: "),
payload.issue.body.indexOf(
"- Provide verification that you are an event organizer: "
) - 2
)
.replace("- Link to the Event Website: ", "");
}

if (payload.issue.title.includes("[In-Person Event]")) {
event_URL = await payload.issue.body
.slice(
payload.issue.body.indexOf("- Link to the Event Website: "),
payload.issue.body.indexOf("- Are you an organizer ") - 2
)
.replace("- Link to the Event Website: ", "");
}
// get badge name
const badge = {
name: assigned_badge,
badgeURL: badge_URL,
};

// get array of assignees
const reviewers = await payload.issue.assignees.map((assignee) => {
return {
name: assignee.login,
github_profile_link: assignee.html_url,
};
});

const application = {
app_no: payload.issue.number,
app_URL: payload.issue.html_url,
};

try {
const newEvent = {
event_name,
event_URL,
badge,
reviewers,
application,
};

const event = await createEvent(newEvent);
if (event) {
return event;
} else {
return "";
}
} catch (error) {
console.error(error);
return "";
}
};

module.exports = saveEvent;
2 changes: 1 addition & 1 deletion event_badging/logic/updateReadme.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ const updateReadme = async (octokit, payload) => {
const event = `[${eventName}](${eventLink})`;

// get badge name
const badge = `![${resultsObj.assignedBadge}]`;
const badge = `![${resultsObj.assigned_badge}]`;

// get array of assignees
const reviewers = await payload.issue.assignees.map((assignee) => {
Expand Down
3 changes: 1 addition & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,8 @@ routes.setupRoutes(app);
* The smee.io service is started using the smee.start() method.
*
*/
const SmeeClient = require("smee-client");
if (process.env.NODE_ENV === "development") {
const SmeeClient = require("smee-client");

const smee = new SmeeClient({
source: `${process.env.SMEECLIENT_URL}`,
target: `http://localhost:${process.env.PORT}/api/event_badging`,
Expand Down
35 changes: 34 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
"husky": "^8.0.3",
"jsonlint": "^1.6.3",
"lint-staged": "^13.2.3",
"prettier": "^2.8.8"
"prettier": "^2.8.8",
"smee-client": "^2.0.1"
}
}
4 changes: 3 additions & 1 deletion providers/github/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,9 @@ const handleOAuthCallback = async (req, res) => {
const octokit = new Octokit({ auth: `${accessToken}` });

// Authenticated user details
const { user_info: userInfo, errors: userInfoErrors } = await getUserInfo(octokit);
const { user_info: userInfo, errors: userInfoErrors } = await getUserInfo(
octokit
);
if (userInfoErrors.length > 0) {
res.status(500).send(userInfoErrors.join());
return;
Expand Down
Loading

0 comments on commit e576c7e

Please sign in to comment.