Skip to content

Commit

Permalink
chore: squash
Browse files Browse the repository at this point in the history
  • Loading branch information
ItsMeBrianD committed Mar 27, 2024
1 parent f5ecd0c commit 9e5d4ef
Show file tree
Hide file tree
Showing 136 changed files with 2,897 additions and 751 deletions.
2 changes: 2 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
.env
50 changes: 50 additions & 0 deletions .github/workflows/build-and-deploy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: Build and Deploy Monorepo

on:
push:
branches:
# - 'preview/**'
# - 'dev/**'
# - 'staging/**'
# - 'main'
- v2

jobs:
build-and-deploy:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3

- name: Build and Push Image
run: |
docker build -t ghcr.io/${{ github.repository }}:${{ github.sha }} .
echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
docker push ghcr.io/${{ github.repository }}:${{ github.sha }}
- name: Extract Environment
id: extract-env
run: |
BRANCH_NAME=${GITHUB_REF##*/}
if [[ $BRANCH_NAME =~ ^preview/ ]]; then
ENV="preview"
elif [[ $BRANCH_NAME =~ ^dev/ ]]; then
ENV="dev"
elif [[ $BRANCH_NAME =~ ^staging/ ]]; then
ENV="staging"
else
ENV="main"
fi
echo "::set-output name=env::$ENV"
- name: Update Nomad Job
run: |
IMAGE_TAG=ghcr.io/${{ github.repository }}:${{ github.sha }}
sed -i "s#__IMAGE_TAG__#$IMAGE_TAG#g" nomad.job.hcl
- name: Deploy to Nomad
uses: hashicorp/nomad-github-action@v1
with:
nomad_addr: ${{ secrets.NOMAD_ADDR }}
nomad_token: ${{ secrets.NOMAD_TOKEN }}
command: job run nomad.job.hcl
8 changes: 0 additions & 8 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -102,23 +102,15 @@ dist

# TernJS port file
.tern-port

*.iml

.idea/

.run/

clients/image-generation-frontend/build/

clients/image-generation-frontend/src/ca-certificate.cer

clients/image-generation-frontend/src/config.json

core/config/development.json.bak

core/config/main.json

core/config/staging.json

# Vim/Emacs backup files
Expand Down
8 changes: 4 additions & 4 deletions .graphqlrc.yaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
projects:
default:
web-client:
schema:
- ./clients/web/schema.graphql
- ./clients/web/$houdini/graphql/schema.graphql
documents:
- './clients/web/**/*.gql'
- './clients/web/**/*.svelte'
- ./clients/web/$houdini/graphql/documents.gql
- "./clients/web/**/*.gql"
- "./clients/web/**/*.svelte"
- "./clients/web/$houdini/graphql/documents.gql"
27 changes: 27 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
FROM oven/bun:1.0.30-alpine as build

ENV PUBLIC_API_PORT=443
ENV PUBLIC_API_URL=api.preview.spr.ocket.gg
ENV PUBLIC_API_SECURE=true

COPY . /app
WORKDIR /app
RUN bun i
RUN cd /app/core && bun run build
RUN cd /app/lib && bun run build
RUN cd /app/services/matchmaking && bun run build
RUN cd /app/clients/discord && bun run build


FROM node:20-alpine

ENV PUBLIC_API_PORT=443
ENV PUBLIC_API_URL=api.preview.spr.ocket.gg
ENV PUBLIC_API_SECURE=true

COPY --from=build /app /app
RUN cd /app/clients/web && npm run build
COPY ./entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

ENTRYPOINT [ "/entrypoint.sh" ]
220 changes: 220 additions & 0 deletions authz-noodles.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
# Sprocket AuthZ

## The Before

Sprocket v1 (here-by _legacy_) had a verbose schema for impelementing Authorization, but it was never fully realized.
The basis was _action_ based access control, where a _user_ could recieve _permission_ from a variety of sources.
The actions were never flushed out, and does not give us much to start with when doing a redesign, but the concept of
where permissions came from remains sound (imo)

In theory (because this was not implemented):

- The "Franchise Manager" "`FranchiseLeadershipRole`" could be created, with the permission to `ManageRoster`
- The "Team Captain" "`FranchiseStaffRole`" with the permission to `ManageRoster`

Some user `shuckle` could be a `Franchise Manager` (by the assignment of a `FranchiseLeadershipSeat`), and
would then be able to manage the roster for their Franchise

Some user `Nigel` could be a `Team Captain` (by the assignment of a `FranchiseStaffSeat`), and would then
be able to manage the roster for their Team

The context of the action could potentially be inferred from where the permission comes from,
e.g.

1. Nigel is the Team Captain of the Grasshoppers Pro League Rocket league Team
1. Nigel attempts to roster HardFault, a Pro League Rocket League player without a team
1. We check that the roster is valid (e.g. skill league, game, and not currently rostered)
2. We check that Nigel has permissions to manage the destination Roster
3. This passes
2. Nigel attempts to roster Zach, an Amateur League Rocket League player without a team
1. The Grasshoppers do have a roster slot available in that league / game
2. Nigel does not have permission to manage the destination Roster
3. This fails

## The After

Sprocket v2 aims to reduce the complexity (or at least make it easier to deal with) compared to legacy Sprocket.
This means that the Authz model taken by v2 should satisfy this goal of being easy for newer developers, while
still retaining the flexibility / power to accomodate the evolving needs of MLE

To that end, `casbin`, an authz library has been brought in, which defines a model, and executes policies against it. It primarily supports RBAC, but it does allow for dynamic roles.

The complexity now comes from creating the correct model, and the correct items to include in that model.

An example:
```conf
[request_definition]
r = subject, object, action, scope
[policy_definition]
p = subject, object, action, scope, effect
[role_definition]
g = _, _
[policy_effect]
e = some(where (p.effect == allow)) && !some(where (p.effect == deny))
[matchers]
m = r.object == p.object && r.action == p.action && g(r.subject, p.subject) && r.scope == p.scope
```

This policy authorizes based on a `subject` (e.g. the user's ID), an `object` (e.g. `FRANCHISE`), `action` (e.g. `MANAGER_ROSTER`), `scope` (e.g. `OWN_ROSTER`) and `effect` (e.g. allow/deny)

This is a flexible system, as it allows for very specific / dynamic policies:
e.g.
```
p, franchise_manager, roster, manage, OWN_FRANCHISE, allow
p, team_captain, roster, manage, OWN_TEAM, allow
g, shuckle, franchise_manager
g, Nigel, team_captain
```

The code is responsible for ensuring that the `scope` is accurate, but requests would look like this:

```
# Nigel attempts to roster HardFault (see above), determined to be OWN_TEAM scope
r, Nigel, roster, manage, OWN_TEAM # Passes
# Nigel attempts to roster Zach (see above), determined to be OWN_FRANCHISE scope
r, Nigel, roster, manage, OWN_FRANCHISE # Fails
```

## Examples

### Scheduling

Scheduling in this instance refers specifically to player availability, and finding
times in which both teams in a fixture can field a full roster.

The actions that need to be taken are:
- Default nobody can read or write schedules
- Players can see their own schedule
- Should this be set per schedule group?
- Team leadership can see their team's detailed schedule
- Team leadership can see their opponents obfuscated schedule **during the schedule group for a fixture**
- League Operations can see all detailed schedules


#### Policy Example
```
# Default deny
p, everybody, schedule, read, all, deny
p, everybody, schedule, write, all, deny
# Allow writing their own schedule
p, everybody, schedule, read, own, allow
p, everybody, schedule, write, own, allow
# How to distinguish between details and obfuscated?
p, team_leadership, schedule, read, own_team, allow
p, team_leadership, schedule, read, opponent, allow
p, league_operations, schedule, read, all, allow
```

#### Hanging Questions
- What should the allow / deny inheritance look like
- e.g. `everybody` is denied read-all schedule access, but `league_operations` is granted it
- Should specificity matter? (e.g. `allow all` beats `deny all`, but `allow all` loses to `deny own`)
- Does this change if the default to _everything_ is deny?
- e.g. the first 2 lines of this policy are no longer relevant, and `league_operations` `read all`
does not conflict with anything
- How do we want to handle differing levels of detail?
- e.g. should we have both `schedule` and `schedule:detail`?
- If so, should `schedule:detail` default to whatever `schedule` is, unless manually specified?
- How would we implement something like this?

### Rostering

Rostering refers to the same example as noted for `legacy` Sprocket

Actions that need to be taken:
- Offering players a spot on the roster
- Withdrawing an extended offer
- Manually assigning players a roster spot (e.g. without offering)
- Removing players from the roster

#### Policy Example
```
p, player, roster:offer, accept, own, allow
p, franchise_leadership, roster:offer, create, own_franchise, allow # Make Offer
p, franchise_leadership, roster:offer, delete, own_franchise, allow # Withdraw Offer
p, franchise_leadership, roster:spot, delete, own_franchise, allow # Remove Player
p, team_leadership, roster:offer, create, own_team, allow # Make Offer
p, team_leadership, roster:offer, delete, own_team, allow # Withdraw offer
p, team_leadership, roster:spot, delete, own_team, allow # Remove Player
p, league_operations, roster:spot, create, all, allow
p, league_operations, roster:spot, delete, all, allow
```

### Scrims

Scrims are a complex topic, because of the management stories involved
Note that the replay submission / ratification process is not covered here, instead it is in [submissions](#submissions)

Actions that need to be taken:
- Participate in scrims
- Listing scrims w/o detailed information
- e.g. when looking for scrims to join
- Listing scrims w/ detailed information
- e.g. when managing scrims
- Listing scrim participation metrics
- Cancelling a scrim
- Manually modifying a scrim's state
- This may not be something we actually want to support
- Applying a scrim ban to a player

#### Policy Example

```
p, player, scrim, participate, own_skill_group, allow
p, player, scrim, read, own_skill_group, allow
p, player, scrim:metrics, read, all, allow
p, support, scrim, read, all, allow
p, support, scrim, read, all, allow
# Read all scrim details except their own
p, support, scrim:detail, read, all, allow
p, support, scrim:detail, read, own, deny
p, admin, scrim, read, all, allow
# Read all scrim details including their own
p, admin, scrim:detail, read, all, allow
```

### Submissions

# Additional stories to write:
> Do all of these actually live in AuthZ or are some of these just basic application flows?
> What level of configurability do we actually care about here?
> Can these be reduced into the default application state, and then an AuthZ action to override it?
- Scheduling
- By default nobody can see any schedules
- Each player can see their own schedule
- Team leadership (incl. franchise) can see their team's whole schedule
- Team leadership (incl. franchise) can see their opponents schedule **during a fixture**
- League Operations can always ee everybody's schedule

- Scrims
- Players can view basic metadata about all scrims
- Mode, Stage, Number of Players
- Players can view detailed information about their own scrim
- Specific players (post-pop only)
- Support can view details about all scrims _except their own_
- Admins can view details about all scrims _including their own_

- Submissions
- Everybody can see the submission status of all submissions
- Team leadership can create submissions for their team's fixtures
- Team leadership can ratify submissions they did not create for their team's fixtures
- Players can create submissions for their current scrim
- Players can ratify submissions they did not create for their current scrim
- League Operations, Support, Admins can reset submissions
Binary file modified bun.lockb
Binary file not shown.
2 changes: 1 addition & 1 deletion clients/web/.graphqlrc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ projects:
documents:
- '**/*.gql'
- '**/*.svelte'
- ./$houdini/graphql/documents.gql
- ./$houdini/graphql/documents.gql
6 changes: 2 additions & 4 deletions clients/web/.vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
{
"prettier.documentSelectors": [
"**/*.svelte"
],
"prettier.documentSelectors": ["**/*.svelte"],
"tailwindCSS.classAttributes": [
"class",
"accent",
Expand Down Expand Up @@ -117,4 +115,4 @@
"width",
"zIndex"
]
}
}
21 changes: 11 additions & 10 deletions clients/web/houdini.config.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
/** @type {import('houdini').ConfigFile} */
const config = {
"watchSchema": {
"url": (env) => {
// Use URL to remove the port if it matches the protocol (e.g. 443 doesn't need to be specified if it's https)
watchSchema: {
url: (env) => {
// Use URL to remove the port if it matches the protocol (e.g. 443 doesn't need to be specified if it's https)
const rawUrl = new URL(
`${env.PUBLIC_API_SECURE.toLowerCase() === 'true' ? 'https' : 'http'}://${env.PUBLIC_API_URL}:${env.PUBLIC_API_PORT}`
`${env.PUBLIC_API_SECURE.toLowerCase() === 'true' ? 'https' : 'http'}://${env.PUBLIC_API_URL}:${env.PUBLIC_API_PORT ?? 443}`
).toString();
// Remove the trailing '/' to make it easier to work with
const apiUrl = rawUrl.endsWith('/') ? rawUrl.substring(0, rawUrl.length - 1) : rawUrl;
console.log(`Using Houdini (config) API @ ${apiUrl}/graphql`)
return `${apiUrl}/graphql`
console.log(`Using Houdini (config) API @ ${apiUrl}/graphql`);
return `${apiUrl}/graphql`;
},
interval: 1000
},
"plugins": {
"houdini-svelte": {}
// schemaPath: path.join(`${import.meta.dirname}`, 'schema.graphql'),
plugins: {
'houdini-svelte': {}
}
}
};

export default config
export default config;
Loading

0 comments on commit 9e5d4ef

Please sign in to comment.