Compare commits
	
		
			No commits in common. "e98bd1f647f85a1b055646b3e662b9207f40681f" and "fcf8f7e3ce5d056aafd120f937778aa8e5045465" have entirely different histories. 
		
	
	
		
			e98bd1f647
			...
			fcf8f7e3ce
		
	
		
	| 
						 | 
					@ -1400,6 +1400,12 @@
 | 
				
			||||||
      "dev": true,
 | 
					      "dev": true,
 | 
				
			||||||
      "license": "MIT"
 | 
					      "license": "MIT"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/@types/web-bluetooth": {
 | 
				
			||||||
 | 
					      "version": "0.0.20",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.20.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==",
 | 
				
			||||||
 | 
					      "license": "MIT"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "node_modules/@types/yauzl": {
 | 
					    "node_modules/@types/yauzl": {
 | 
				
			||||||
      "version": "2.10.3",
 | 
					      "version": "2.10.3",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz",
 | 
				
			||||||
| 
						 | 
					@ -2029,6 +2035,56 @@
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/@vueuse/core": {
 | 
				
			||||||
 | 
					      "version": "10.11.1",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.11.1.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-guoy26JQktXPcz+0n3GukWIy/JDNKti9v6VEMu6kV2sYBsWuGiTU8OWdg+ADfUbHg3/3DlqySDe7JmdHrktiww==",
 | 
				
			||||||
 | 
					      "license": "MIT",
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "@types/web-bluetooth": "^0.0.20",
 | 
				
			||||||
 | 
					        "@vueuse/metadata": "10.11.1",
 | 
				
			||||||
 | 
					        "@vueuse/shared": "10.11.1",
 | 
				
			||||||
 | 
					        "vue-demi": ">=0.14.8"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "funding": {
 | 
				
			||||||
 | 
					        "url": "https://github.com/sponsors/antfu"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/@vueuse/core/node_modules/vue-demi": {
 | 
				
			||||||
 | 
					      "version": "0.14.10",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==",
 | 
				
			||||||
 | 
					      "hasInstallScript": true,
 | 
				
			||||||
 | 
					      "license": "MIT",
 | 
				
			||||||
 | 
					      "bin": {
 | 
				
			||||||
 | 
					        "vue-demi-fix": "bin/vue-demi-fix.js",
 | 
				
			||||||
 | 
					        "vue-demi-switch": "bin/vue-demi-switch.js"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "engines": {
 | 
				
			||||||
 | 
					        "node": ">=12"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "funding": {
 | 
				
			||||||
 | 
					        "url": "https://github.com/sponsors/antfu"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "peerDependencies": {
 | 
				
			||||||
 | 
					        "@vue/composition-api": "^1.0.0-rc.1",
 | 
				
			||||||
 | 
					        "vue": "^3.0.0-0 || ^2.6.0"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "peerDependenciesMeta": {
 | 
				
			||||||
 | 
					        "@vue/composition-api": {
 | 
				
			||||||
 | 
					          "optional": true
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/@vueuse/metadata": {
 | 
				
			||||||
 | 
					      "version": "10.11.1",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.11.1.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-IGa5FXd003Ug1qAZmyE8wF3sJ81xGLSqTqtQ6jaVfkeZ4i5kS2mwQF61yhVqojRnenVew5PldLyRgvdl4YYuSw==",
 | 
				
			||||||
 | 
					      "license": "MIT",
 | 
				
			||||||
 | 
					      "funding": {
 | 
				
			||||||
 | 
					        "url": "https://github.com/sponsors/antfu"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "node_modules/@vueuse/shared": {
 | 
					    "node_modules/@vueuse/shared": {
 | 
				
			||||||
      "version": "10.11.1",
 | 
					      "version": "10.11.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.11.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.11.1.tgz",
 | 
				
			||||||
| 
						 | 
					@ -6343,62 +6399,6 @@
 | 
				
			||||||
        "vue": ">= 3.2.0"
 | 
					        "vue": ">= 3.2.0"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "node_modules/radix-vue/node_modules/@types/web-bluetooth": {
 | 
					 | 
				
			||||||
      "version": "0.0.20",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.20.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==",
 | 
					 | 
				
			||||||
      "license": "MIT"
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "node_modules/radix-vue/node_modules/@vueuse/core": {
 | 
					 | 
				
			||||||
      "version": "10.11.1",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.11.1.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha512-guoy26JQktXPcz+0n3GukWIy/JDNKti9v6VEMu6kV2sYBsWuGiTU8OWdg+ADfUbHg3/3DlqySDe7JmdHrktiww==",
 | 
					 | 
				
			||||||
      "license": "MIT",
 | 
					 | 
				
			||||||
      "dependencies": {
 | 
					 | 
				
			||||||
        "@types/web-bluetooth": "^0.0.20",
 | 
					 | 
				
			||||||
        "@vueuse/metadata": "10.11.1",
 | 
					 | 
				
			||||||
        "@vueuse/shared": "10.11.1",
 | 
					 | 
				
			||||||
        "vue-demi": ">=0.14.8"
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "funding": {
 | 
					 | 
				
			||||||
        "url": "https://github.com/sponsors/antfu"
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "node_modules/radix-vue/node_modules/@vueuse/core/node_modules/vue-demi": {
 | 
					 | 
				
			||||||
      "version": "0.14.10",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==",
 | 
					 | 
				
			||||||
      "hasInstallScript": true,
 | 
					 | 
				
			||||||
      "license": "MIT",
 | 
					 | 
				
			||||||
      "bin": {
 | 
					 | 
				
			||||||
        "vue-demi-fix": "bin/vue-demi-fix.js",
 | 
					 | 
				
			||||||
        "vue-demi-switch": "bin/vue-demi-switch.js"
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "engines": {
 | 
					 | 
				
			||||||
        "node": ">=12"
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "funding": {
 | 
					 | 
				
			||||||
        "url": "https://github.com/sponsors/antfu"
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "peerDependencies": {
 | 
					 | 
				
			||||||
        "@vue/composition-api": "^1.0.0-rc.1",
 | 
					 | 
				
			||||||
        "vue": "^3.0.0-0 || ^2.6.0"
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "peerDependenciesMeta": {
 | 
					 | 
				
			||||||
        "@vue/composition-api": {
 | 
					 | 
				
			||||||
          "optional": true
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "node_modules/radix-vue/node_modules/@vueuse/metadata": {
 | 
					 | 
				
			||||||
      "version": "10.11.1",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.11.1.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha512-IGa5FXd003Ug1qAZmyE8wF3sJ81xGLSqTqtQ6jaVfkeZ4i5kS2mwQF61yhVqojRnenVew5PldLyRgvdl4YYuSw==",
 | 
					 | 
				
			||||||
      "license": "MIT",
 | 
					 | 
				
			||||||
      "funding": {
 | 
					 | 
				
			||||||
        "url": "https://github.com/sponsors/antfu"
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "node_modules/radix-vue/node_modules/nanoid": {
 | 
					    "node_modules/radix-vue/node_modules/nanoid": {
 | 
				
			||||||
      "version": "5.0.9",
 | 
					      "version": "5.0.9",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.9.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.9.tgz",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -421,69 +421,3 @@ tr:last-child > td:first-child {
 | 
				
			||||||
tr:last-child > td:last-child {
 | 
					tr:last-child > td:last-child {
 | 
				
			||||||
  border-bottom-right-radius: 4px;
 | 
					  border-bottom-right-radius: 4px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
.sidebar-container {
 | 
					 | 
				
			||||||
  display: flex;
 | 
					 | 
				
			||||||
  gap: 16px;
 | 
					 | 
				
			||||||
  justify-content: center;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.sidebar-container nav.sidebar {
 | 
					 | 
				
			||||||
  display: flex;
 | 
					 | 
				
			||||||
  justify-content: end;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.sidebar-container .view {
 | 
					 | 
				
			||||||
  width: 60%;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
nav.sidebar h3 {
 | 
					 | 
				
			||||||
  text-transform: uppercase;
 | 
					 | 
				
			||||||
  color: var(--overlay-0);
 | 
					 | 
				
			||||||
  padding: 0 8px;
 | 
					 | 
				
			||||||
  font-size: 8pt;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
nav.sidebar > .categories {
 | 
					 | 
				
			||||||
  display: flex;
 | 
					 | 
				
			||||||
  flex-direction: column;
 | 
					 | 
				
			||||||
  width: 192px;
 | 
					 | 
				
			||||||
  gap: 4px;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
nav.sidebar a.tab {
 | 
					 | 
				
			||||||
  font-size: 11pt;
 | 
					 | 
				
			||||||
  color: var(--overlay-0);
 | 
					 | 
				
			||||||
  padding: 6px 10px;
 | 
					 | 
				
			||||||
  font-weight: 500;
 | 
					 | 
				
			||||||
  border-radius: 4px;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
nav.sidebar a.tab:hover {
 | 
					 | 
				
			||||||
  background-color: var(--crust);
 | 
					 | 
				
			||||||
  color: var(--text);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
nav.sidebar a.tab.router-link-exact-active {
 | 
					 | 
				
			||||||
  background-color: var(--crust);
 | 
					 | 
				
			||||||
  color: var(--text);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
nav.sidebar button {
 | 
					 | 
				
			||||||
  font-size: 11pt;
 | 
					 | 
				
			||||||
  font-weight: 500;
 | 
					 | 
				
			||||||
  padding: 6px 10px;
 | 
					 | 
				
			||||||
  background-color: transparent;
 | 
					 | 
				
			||||||
  color: var(--overlay-0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
nav.sidebar button:hover {
 | 
					 | 
				
			||||||
  background-color: var(--crust);
 | 
					 | 
				
			||||||
  color: var(--text);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
nav.sidebar button.destructive-on-hover:hover {
 | 
					 | 
				
			||||||
  background-color: var(--destructive);
 | 
					 | 
				
			||||||
  color: var(--base);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,12 +22,10 @@ export type { EventWithPlayerSchema } from './models/EventWithPlayerSchema';
 | 
				
			||||||
export type { EventWithPlayerSchemaList } from './models/EventWithPlayerSchemaList';
 | 
					export type { EventWithPlayerSchemaList } from './models/EventWithPlayerSchemaList';
 | 
				
			||||||
export type { GetEventPlayersResponse } from './models/GetEventPlayersResponse';
 | 
					export type { GetEventPlayersResponse } from './models/GetEventPlayersResponse';
 | 
				
			||||||
export type { GetMatchQuery } from './models/GetMatchQuery';
 | 
					export type { GetMatchQuery } from './models/GetMatchQuery';
 | 
				
			||||||
export type { GetUserResponse } from './models/GetUserResponse';
 | 
					 | 
				
			||||||
export type { MatchSchema } from './models/MatchSchema';
 | 
					export type { MatchSchema } from './models/MatchSchema';
 | 
				
			||||||
export type { PlayerEventRolesSchema } from './models/PlayerEventRolesSchema';
 | 
					export type { PlayerEventRolesSchema } from './models/PlayerEventRolesSchema';
 | 
				
			||||||
export type { PlayerRoleSchema } from './models/PlayerRoleSchema';
 | 
					export type { PlayerRoleSchema } from './models/PlayerRoleSchema';
 | 
				
			||||||
export type { PlayerSchema } from './models/PlayerSchema';
 | 
					export type { PlayerSchema } from './models/PlayerSchema';
 | 
				
			||||||
export type { PlayerSchemaList } from './models/PlayerSchemaList';
 | 
					 | 
				
			||||||
export type { PlayerTeamAvailabilityRoleSchema } from './models/PlayerTeamAvailabilityRoleSchema';
 | 
					export type { PlayerTeamAvailabilityRoleSchema } from './models/PlayerTeamAvailabilityRoleSchema';
 | 
				
			||||||
export type { PutScheduleForm } from './models/PutScheduleForm';
 | 
					export type { PutScheduleForm } from './models/PutScheduleForm';
 | 
				
			||||||
export type { RoleSchema } from './models/RoleSchema';
 | 
					export type { RoleSchema } from './models/RoleSchema';
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,12 +0,0 @@
 | 
				
			||||||
/* generated using openapi-typescript-codegen -- do not edit */
 | 
					 | 
				
			||||||
/* istanbul ignore file */
 | 
					 | 
				
			||||||
/* tslint:disable */
 | 
					 | 
				
			||||||
/* eslint-disable */
 | 
					 | 
				
			||||||
import type { PlayerSchema } from './PlayerSchema';
 | 
					 | 
				
			||||||
export type GetUserResponse = {
 | 
					 | 
				
			||||||
    isAdmin?: boolean;
 | 
					 | 
				
			||||||
    realUser: (PlayerSchema | null);
 | 
					 | 
				
			||||||
    steamId: string;
 | 
					 | 
				
			||||||
    username: string;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					@ -3,7 +3,6 @@
 | 
				
			||||||
/* tslint:disable */
 | 
					/* tslint:disable */
 | 
				
			||||||
/* eslint-disable */
 | 
					/* eslint-disable */
 | 
				
			||||||
export type PlayerSchema = {
 | 
					export type PlayerSchema = {
 | 
				
			||||||
    isAdmin?: boolean;
 | 
					 | 
				
			||||||
    steamId: string;
 | 
					    steamId: string;
 | 
				
			||||||
    username: string;
 | 
					    username: string;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +0,0 @@
 | 
				
			||||||
/* generated using openapi-typescript-codegen -- do not edit */
 | 
					 | 
				
			||||||
/* istanbul ignore file */
 | 
					 | 
				
			||||||
/* tslint:disable */
 | 
					 | 
				
			||||||
/* eslint-disable */
 | 
					 | 
				
			||||||
import type { PlayerSchema } from './PlayerSchema';
 | 
					 | 
				
			||||||
export type PlayerSchemaList = Array<PlayerSchema>;
 | 
					 | 
				
			||||||
| 
						 | 
					@ -6,7 +6,6 @@ import type { RoleSchema } from './RoleSchema';
 | 
				
			||||||
export type ViewTeamMembersResponse = {
 | 
					export type ViewTeamMembersResponse = {
 | 
				
			||||||
    availability: Array<number>;
 | 
					    availability: Array<number>;
 | 
				
			||||||
    createdAt: string;
 | 
					    createdAt: string;
 | 
				
			||||||
    isAdmin?: boolean;
 | 
					 | 
				
			||||||
    isTeamLeader?: boolean;
 | 
					    isTeamLeader?: boolean;
 | 
				
			||||||
    playtime: number;
 | 
					    playtime: number;
 | 
				
			||||||
    roles: Array<RoleSchema>;
 | 
					    roles: Array<RoleSchema>;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,10 +12,8 @@ import type { EventSchema } from '../models/EventSchema';
 | 
				
			||||||
import type { EventWithPlayerSchema } from '../models/EventWithPlayerSchema';
 | 
					import type { EventWithPlayerSchema } from '../models/EventWithPlayerSchema';
 | 
				
			||||||
import type { EventWithPlayerSchemaList } from '../models/EventWithPlayerSchemaList';
 | 
					import type { EventWithPlayerSchemaList } from '../models/EventWithPlayerSchemaList';
 | 
				
			||||||
import type { GetEventPlayersResponse } from '../models/GetEventPlayersResponse';
 | 
					import type { GetEventPlayersResponse } from '../models/GetEventPlayersResponse';
 | 
				
			||||||
import type { GetUserResponse } from '../models/GetUserResponse';
 | 
					 | 
				
			||||||
import type { MatchSchema } from '../models/MatchSchema';
 | 
					import type { MatchSchema } from '../models/MatchSchema';
 | 
				
			||||||
import type { PlayerSchema } from '../models/PlayerSchema';
 | 
					import type { PlayerSchema } from '../models/PlayerSchema';
 | 
				
			||||||
import type { PlayerSchemaList } from '../models/PlayerSchemaList';
 | 
					 | 
				
			||||||
import type { PutScheduleForm } from '../models/PutScheduleForm';
 | 
					import type { PutScheduleForm } from '../models/PutScheduleForm';
 | 
				
			||||||
import type { SetUsernameJson } from '../models/SetUsernameJson';
 | 
					import type { SetUsernameJson } from '../models/SetUsernameJson';
 | 
				
			||||||
import type { SubmitMatchJson } from '../models/SubmitMatchJson';
 | 
					import type { SubmitMatchJson } from '../models/SubmitMatchJson';
 | 
				
			||||||
| 
						 | 
					@ -281,10 +279,10 @@ export class DefaultService {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * get_user <GET>
 | 
					     * get_user <GET>
 | 
				
			||||||
     * @returns GetUserResponse OK
 | 
					     * @returns PlayerSchema OK
 | 
				
			||||||
     * @throws ApiError
 | 
					     * @throws ApiError
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public getUser(): CancelablePromise<GetUserResponse> {
 | 
					    public getUser(): CancelablePromise<PlayerSchema> {
 | 
				
			||||||
        return this.httpRequest.request({
 | 
					        return this.httpRequest.request({
 | 
				
			||||||
            method: 'GET',
 | 
					            method: 'GET',
 | 
				
			||||||
            url: '/api/login/get-user',
 | 
					            url: '/api/login/get-user',
 | 
				
			||||||
| 
						 | 
					@ -520,6 +518,28 @@ export class DefaultService {
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * delete_team <DELETE>
 | 
				
			||||||
 | 
					     * @param teamId
 | 
				
			||||||
 | 
					     * @returns any OK
 | 
				
			||||||
 | 
					     * @throws ApiError
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public deleteTeam(
 | 
				
			||||||
 | 
					        teamId: number,
 | 
				
			||||||
 | 
					    ): CancelablePromise<any> {
 | 
				
			||||||
 | 
					        return this.httpRequest.request({
 | 
				
			||||||
 | 
					            method: 'DELETE',
 | 
				
			||||||
 | 
					            url: '/api/team/id/{team_id}/',
 | 
				
			||||||
 | 
					            path: {
 | 
				
			||||||
 | 
					                'team_id': teamId,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            errors: {
 | 
				
			||||||
 | 
					                403: `Forbidden`,
 | 
				
			||||||
 | 
					                404: `Not Found`,
 | 
				
			||||||
 | 
					                422: `Unprocessable Content`,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * view_team <GET>
 | 
					     * view_team <GET>
 | 
				
			||||||
     * @param teamId
 | 
					     * @param teamId
 | 
				
			||||||
| 
						 | 
					@ -781,54 +801,6 @@ export class DefaultService {
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * get_all_users <GET>
 | 
					 | 
				
			||||||
     * @returns PlayerSchemaList OK
 | 
					 | 
				
			||||||
     * @throws ApiError
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public getAllUsers(): CancelablePromise<PlayerSchemaList> {
 | 
					 | 
				
			||||||
        return this.httpRequest.request({
 | 
					 | 
				
			||||||
            method: 'GET',
 | 
					 | 
				
			||||||
            url: '/api/user/all',
 | 
					 | 
				
			||||||
            errors: {
 | 
					 | 
				
			||||||
                422: `Unprocessable Content`,
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * unset_doas <DELETE>
 | 
					 | 
				
			||||||
     * @returns void
 | 
					 | 
				
			||||||
     * @throws ApiError
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public unsetDoas(): CancelablePromise<void> {
 | 
					 | 
				
			||||||
        return this.httpRequest.request({
 | 
					 | 
				
			||||||
            method: 'DELETE',
 | 
					 | 
				
			||||||
            url: '/api/user/doas',
 | 
					 | 
				
			||||||
            errors: {
 | 
					 | 
				
			||||||
                422: `Unprocessable Content`,
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * set_doas <PUT>
 | 
					 | 
				
			||||||
     * @param steamId
 | 
					 | 
				
			||||||
     * @returns PlayerSchema OK
 | 
					 | 
				
			||||||
     * @throws ApiError
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public setDoas(
 | 
					 | 
				
			||||||
        steamId: string,
 | 
					 | 
				
			||||||
    ): CancelablePromise<PlayerSchema> {
 | 
					 | 
				
			||||||
        return this.httpRequest.request({
 | 
					 | 
				
			||||||
            method: 'PUT',
 | 
					 | 
				
			||||||
            url: '/api/user/doas/{steam_id}',
 | 
					 | 
				
			||||||
            path: {
 | 
					 | 
				
			||||||
                'steam_id': steamId,
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            errors: {
 | 
					 | 
				
			||||||
                422: `Unprocessable Content`,
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * set_username <POST>
 | 
					     * set_username <POST>
 | 
				
			||||||
     * @param requestBody
 | 
					     * @param requestBody
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,9 +19,6 @@ function logout() {
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
  <DropdownMenuRoot>
 | 
					  <DropdownMenuRoot>
 | 
				
			||||||
    <DropdownMenuTrigger className="profile-button no-border">
 | 
					    <DropdownMenuTrigger className="profile-button no-border">
 | 
				
			||||||
      <span class="aside" v-if="authStore.realUser">
 | 
					 | 
				
			||||||
        {{ authStore.realUser?.username }}, disguised as
 | 
					 | 
				
			||||||
      </span>
 | 
					 | 
				
			||||||
      {{ authStore.username }}
 | 
					      {{ authStore.username }}
 | 
				
			||||||
      <i class="bi bi-chevron-down" />
 | 
					      <i class="bi bi-chevron-down" />
 | 
				
			||||||
    </DropdownMenuTrigger>
 | 
					    </DropdownMenuTrigger>
 | 
				
			||||||
| 
						 | 
					@ -43,14 +40,6 @@ function logout() {
 | 
				
			||||||
            </button>
 | 
					            </button>
 | 
				
			||||||
          </RouterLink>
 | 
					          </RouterLink>
 | 
				
			||||||
        </DropdownMenuItem>
 | 
					        </DropdownMenuItem>
 | 
				
			||||||
        <DropdownMenuItem v-if="authStore.isAdmin">
 | 
					 | 
				
			||||||
          <RouterLink class="button" :to="{ 'name': 'admin' }">
 | 
					 | 
				
			||||||
            <button>
 | 
					 | 
				
			||||||
              <i class="bi bi-person-check margin" />
 | 
					 | 
				
			||||||
              Super secret admin stuff!
 | 
					 | 
				
			||||||
            </button>
 | 
					 | 
				
			||||||
          </RouterLink>
 | 
					 | 
				
			||||||
        </DropdownMenuItem>
 | 
					 | 
				
			||||||
        <DropdownMenuItem>
 | 
					        <DropdownMenuItem>
 | 
				
			||||||
          <button class="destructive" @click="logout">
 | 
					          <button class="destructive" @click="logout">
 | 
				
			||||||
            <i class="bi bi-box-arrow-right margin" />
 | 
					            <i class="bi bi-box-arrow-right margin" />
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,9 +13,6 @@ import TeamSettingsIntegrationsView from "@/views/TeamSettings/IntegrationsView.
 | 
				
			||||||
import TeamSettingsInvitesView from "@/views/TeamSettings/InvitesView.vue";
 | 
					import TeamSettingsInvitesView from "@/views/TeamSettings/InvitesView.vue";
 | 
				
			||||||
import TeamSettingsMatchesView from "@/views/TeamSettings/MatchesView.vue";
 | 
					import TeamSettingsMatchesView from "@/views/TeamSettings/MatchesView.vue";
 | 
				
			||||||
import UserSettingsView from "@/views/UserSettingsView.vue";
 | 
					import UserSettingsView from "@/views/UserSettingsView.vue";
 | 
				
			||||||
import AdminView from "@/views/AdminView.vue";
 | 
					 | 
				
			||||||
import AdminGeneralView from "@/views/Admin/GeneralView.vue";
 | 
					 | 
				
			||||||
import AdminDoasView from "@/views/Admin/DoasView.vue";
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
const router = createRouter({
 | 
					const router = createRouter({
 | 
				
			||||||
  history: createWebHistory(import.meta.env.BASE_URL),
 | 
					  history: createWebHistory(import.meta.env.BASE_URL),
 | 
				
			||||||
| 
						 | 
					@ -87,23 +84,6 @@ const router = createRouter({
 | 
				
			||||||
      name: "user-settings",
 | 
					      name: "user-settings",
 | 
				
			||||||
      component: UserSettingsView,
 | 
					      component: UserSettingsView,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      path: "/admin",
 | 
					 | 
				
			||||||
      name: "admin",
 | 
					 | 
				
			||||||
      component: AdminView,
 | 
					 | 
				
			||||||
      children: [
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
          path: "",
 | 
					 | 
				
			||||||
          name: "admin/",
 | 
					 | 
				
			||||||
          component: AdminGeneralView,
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
          path: "doas",
 | 
					 | 
				
			||||||
          name: "admin/doas",
 | 
					 | 
				
			||||||
          component: AdminDoasView,
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
      ],
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
  ]
 | 
					  ]
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,20 +2,18 @@ import { defineStore } from "pinia";
 | 
				
			||||||
import { ref } from "vue";
 | 
					import { ref } from "vue";
 | 
				
			||||||
import { useClientStore } from "./client";
 | 
					import { useClientStore } from "./client";
 | 
				
			||||||
import { useRouter, type LocationQuery } from "vue-router";
 | 
					import { useRouter, type LocationQuery } from "vue-router";
 | 
				
			||||||
import { type GetUserResponse, type PlayerSchema } from "@/client";
 | 
					import { type PlayerSchema } from "@/client";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const useAuthStore = defineStore("auth", () => {
 | 
					export const useAuthStore = defineStore("auth", () => {
 | 
				
			||||||
  const clientStore = useClientStore();
 | 
					  const clientStore = useClientStore();
 | 
				
			||||||
  const client = clientStore.client;
 | 
					  const client = clientStore.client;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const user = ref<GetUserResponse | null>(null);
 | 
					  const user = ref<PlayerSchema | null>(null);
 | 
				
			||||||
  const steamId = ref("");
 | 
					  const steamId = ref("");
 | 
				
			||||||
  const username = ref("");
 | 
					  const username = ref("");
 | 
				
			||||||
  const isLoggedIn = ref(false);
 | 
					  const isLoggedIn = ref(false);
 | 
				
			||||||
  const isRegistering = ref(false);
 | 
					  const isRegistering = ref(false);
 | 
				
			||||||
  const hasCheckedAuth = ref(false);
 | 
					  const hasCheckedAuth = ref(false);
 | 
				
			||||||
  const isAdmin = ref(false);
 | 
					 | 
				
			||||||
  const realUser = ref<PlayerSchema | null>(null);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const router = useRouter();
 | 
					  const router = useRouter();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -37,9 +35,6 @@ export const useAuthStore = defineStore("auth", () => {
 | 
				
			||||||
        steamId.value = response.steamId;
 | 
					        steamId.value = response.steamId;
 | 
				
			||||||
        username.value = response.username;
 | 
					        username.value = response.username;
 | 
				
			||||||
        user.value = response;
 | 
					        user.value = response;
 | 
				
			||||||
        isAdmin.value = response.isAdmin || (response.realUser?.isAdmin ?? false);
 | 
					 | 
				
			||||||
        realUser.value = response.realUser ?? null;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return response;
 | 
					        return response;
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      undefined,
 | 
					      undefined,
 | 
				
			||||||
| 
						 | 
					@ -81,48 +76,13 @@ export const useAuthStore = defineStore("auth", () => {
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async function getAllUsers() {
 | 
					 | 
				
			||||||
    return client.default.getAllUsers();
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  async function setDoas(doasSteamId: string) {
 | 
					 | 
				
			||||||
    return client.default.setDoas(doasSteamId)
 | 
					 | 
				
			||||||
      .then((response) => {
 | 
					 | 
				
			||||||
        if (user.value) {
 | 
					 | 
				
			||||||
          realUser.value = {
 | 
					 | 
				
			||||||
            steamId: user.value.steamId,
 | 
					 | 
				
			||||||
            username: user.value.username,
 | 
					 | 
				
			||||||
            isAdmin: user.value.isAdmin,
 | 
					 | 
				
			||||||
          };
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        steamId.value = response.steamId;
 | 
					 | 
				
			||||||
        username.value = response.username;
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  async function unsetDoas() {
 | 
					 | 
				
			||||||
    return client.default.unsetDoas()
 | 
					 | 
				
			||||||
      .then((_) => {
 | 
					 | 
				
			||||||
        if (realUser.value) {
 | 
					 | 
				
			||||||
          steamId.value = realUser.value.steamId;
 | 
					 | 
				
			||||||
          username.value = realUser.value.username;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        realUser.value = null;
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return {
 | 
					  return {
 | 
				
			||||||
    steamId,
 | 
					    steamId,
 | 
				
			||||||
    username,
 | 
					    username,
 | 
				
			||||||
    isAdmin,
 | 
					 | 
				
			||||||
    realUser,
 | 
					 | 
				
			||||||
    isLoggedIn,
 | 
					    isLoggedIn,
 | 
				
			||||||
    hasCheckedAuth,
 | 
					    hasCheckedAuth,
 | 
				
			||||||
    isRegistering,
 | 
					    isRegistering,
 | 
				
			||||||
    getUser,
 | 
					    getUser,
 | 
				
			||||||
    getAllUsers,
 | 
					 | 
				
			||||||
    setDoas,
 | 
					 | 
				
			||||||
    unsetDoas,
 | 
					 | 
				
			||||||
    login,
 | 
					    login,
 | 
				
			||||||
    logout,
 | 
					    logout,
 | 
				
			||||||
    setUsername,
 | 
					    setUsername,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,64 +0,0 @@
 | 
				
			||||||
<script setup lang="ts">
 | 
					 | 
				
			||||||
import { type PlayerSchema, type PlayerSchemaList } from "@/client";
 | 
					 | 
				
			||||||
import { useAuthStore } from "@/stores/auth";
 | 
					 | 
				
			||||||
import { onMounted, ref } from "vue";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//const cookies = useCookies(["doas"], { doNotParse: true, autoUpdateDependencies: true }, universalCookie);
 | 
					 | 
				
			||||||
const doas = ref<PlayerSchema | undefined>();
 | 
					 | 
				
			||||||
const users = ref<PlayerSchemaList>([]);
 | 
					 | 
				
			||||||
const authStore = useAuthStore();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
onMounted(() => {
 | 
					 | 
				
			||||||
  authStore.getAllUsers()
 | 
					 | 
				
			||||||
    .then((response) => {
 | 
					 | 
				
			||||||
      users.value = response;
 | 
					 | 
				
			||||||
      //doas.value = response.find(user => user.steamId === cookies.get("doas"));
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function setDoas() {
 | 
					 | 
				
			||||||
  if (doas.value) {
 | 
					 | 
				
			||||||
    authStore.setDoas(doas.value.steamId);
 | 
					 | 
				
			||||||
  } else {
 | 
					 | 
				
			||||||
    authStore.unsetDoas();
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function removeDoas() {
 | 
					 | 
				
			||||||
  doas.value = undefined;
 | 
					 | 
				
			||||||
  authStore.unsetDoas();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<template>
 | 
					 | 
				
			||||||
  <h2>Become User</h2>
 | 
					 | 
				
			||||||
  <p>
 | 
					 | 
				
			||||||
    Do as/become a specific user.
 | 
					 | 
				
			||||||
  </p>
 | 
					 | 
				
			||||||
  <div>
 | 
					 | 
				
			||||||
    <div class="form-group margin">
 | 
					 | 
				
			||||||
      <h3>User</h3>
 | 
					 | 
				
			||||||
      <v-select
 | 
					 | 
				
			||||||
        v-model="doas"
 | 
					 | 
				
			||||||
        :options="users"
 | 
					 | 
				
			||||||
        label="username"
 | 
					 | 
				
			||||||
        placeholder="Select a user"
 | 
					 | 
				
			||||||
        :clearable="true"
 | 
					 | 
				
			||||||
        :searchable="true"
 | 
					 | 
				
			||||||
        :close-on-select="true"
 | 
					 | 
				
			||||||
        :show-search-input="true"
 | 
					 | 
				
			||||||
      />
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
    <div class="form-group margin">
 | 
					 | 
				
			||||||
      <div class="action-buttons">
 | 
					 | 
				
			||||||
        <button class="destructive-on-hover" @click="removeDoas">
 | 
					 | 
				
			||||||
          <i class="bi bi-trash" />
 | 
					 | 
				
			||||||
        </button>
 | 
					 | 
				
			||||||
        <button class="accent" @click="setDoas">
 | 
					 | 
				
			||||||
          <i class="bi bi-check" />
 | 
					 | 
				
			||||||
          Become {{ doas?.username }}
 | 
					 | 
				
			||||||
        </button>
 | 
					 | 
				
			||||||
      </div>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
</template>
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,9 +0,0 @@
 | 
				
			||||||
<script setup lang="ts">
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<template>
 | 
					 | 
				
			||||||
  <h1>Admin Panel</h1>
 | 
					 | 
				
			||||||
  <p>
 | 
					 | 
				
			||||||
    This is the admin panel. Only admins can access this page.
 | 
					 | 
				
			||||||
  </p>
 | 
					 | 
				
			||||||
</template>
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,22 +0,0 @@
 | 
				
			||||||
<script setup lang="ts">
 | 
					 | 
				
			||||||
import { RouterLink, RouterView } from "vue-router";
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<template>
 | 
					 | 
				
			||||||
  <main class="sidebar-container admin-panel">
 | 
					 | 
				
			||||||
    <nav class="sidebar">
 | 
					 | 
				
			||||||
      <div class="categories">
 | 
					 | 
				
			||||||
        <h3>Admin Panel</h3>
 | 
					 | 
				
			||||||
        <RouterLink class="tab" :to="{ name: 'admin/' }">
 | 
					 | 
				
			||||||
          General
 | 
					 | 
				
			||||||
        </RouterLink>
 | 
					 | 
				
			||||||
        <RouterLink class="tab" :to="{ name: 'admin/doas' }">
 | 
					 | 
				
			||||||
          Become User
 | 
					 | 
				
			||||||
        </RouterLink>
 | 
					 | 
				
			||||||
      </div>
 | 
					 | 
				
			||||||
    </nav>
 | 
					 | 
				
			||||||
    <div class="view">
 | 
					 | 
				
			||||||
      <RouterView />
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
  </main>
 | 
					 | 
				
			||||||
</template>
 | 
					 | 
				
			||||||
| 
						 | 
					@ -23,7 +23,7 @@ onMounted(() => {
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
  <main class="sidebar-container team-settings" v-if="team">
 | 
					  <main class="team-settings" v-if="team">
 | 
				
			||||||
    <nav class="sidebar">
 | 
					    <nav class="sidebar">
 | 
				
			||||||
      <div class="categories">
 | 
					      <div class="categories">
 | 
				
			||||||
        <div class="back-link">
 | 
					        <div class="back-link">
 | 
				
			||||||
| 
						 | 
					@ -59,7 +59,72 @@ onMounted(() => {
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<style scoped>
 | 
					<style scoped>
 | 
				
			||||||
 | 
					.team-settings {
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  gap: 16px;
 | 
				
			||||||
 | 
					  justify-content: center;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.team-settings nav.sidebar {
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  justify-content: end;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.team-settings .view {
 | 
				
			||||||
 | 
					  width: 60%;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.back-link {
 | 
					.back-link {
 | 
				
			||||||
  padding: 8px 16px;
 | 
					  padding: 8px 16px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					nav.sidebar h3 {
 | 
				
			||||||
 | 
					  text-transform: uppercase;
 | 
				
			||||||
 | 
					  color: var(--overlay-0);
 | 
				
			||||||
 | 
					  padding: 0 8px;
 | 
				
			||||||
 | 
					  font-size: 8pt;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					nav.sidebar > .categories {
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  flex-direction: column;
 | 
				
			||||||
 | 
					  width: 192px;
 | 
				
			||||||
 | 
					  gap: 4px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					nav.sidebar a.tab {
 | 
				
			||||||
 | 
					  font-size: 11pt;
 | 
				
			||||||
 | 
					  color: var(--overlay-0);
 | 
				
			||||||
 | 
					  padding: 6px 10px;
 | 
				
			||||||
 | 
					  font-weight: 500;
 | 
				
			||||||
 | 
					  border-radius: 4px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					nav.sidebar a.tab:hover {
 | 
				
			||||||
 | 
					  background-color: var(--crust);
 | 
				
			||||||
 | 
					  color: var(--text);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					nav.sidebar a.tab.router-link-exact-active {
 | 
				
			||||||
 | 
					  background-color: var(--crust);
 | 
				
			||||||
 | 
					  color: var(--text);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					nav.sidebar button {
 | 
				
			||||||
 | 
					  font-size: 11pt;
 | 
				
			||||||
 | 
					  font-weight: 500;
 | 
				
			||||||
 | 
					  padding: 6px 10px;
 | 
				
			||||||
 | 
					  background-color: transparent;
 | 
				
			||||||
 | 
					  color: var(--overlay-0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					nav.sidebar button:hover {
 | 
				
			||||||
 | 
					  background-color: var(--crust);
 | 
				
			||||||
 | 
					  color: var(--text);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					nav.sidebar button.destructive-on-hover:hover {
 | 
				
			||||||
 | 
					  background-color: var(--destructive);
 | 
				
			||||||
 | 
					  color: var(--base);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
</style>
 | 
					</style>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,36 +21,17 @@ STEAM_OPENID_URL = "https://steamcommunity.com/openid/login"
 | 
				
			||||||
def index():
 | 
					def index():
 | 
				
			||||||
    return "test"
 | 
					    return "test"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class GetUserResponse(PlayerSchema):
 | 
					 | 
				
			||||||
    real_user: PlayerSchema | None
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @classmethod
 | 
					 | 
				
			||||||
    def from_model(cls, model: Player):
 | 
					 | 
				
			||||||
        return GetUserResponse(
 | 
					 | 
				
			||||||
            steam_id=str(model.steam_id),
 | 
					 | 
				
			||||||
            username=model.username,
 | 
					 | 
				
			||||||
            is_admin=model.is_admin,
 | 
					 | 
				
			||||||
            real_user=None,
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@api_login.get("/get-user")
 | 
					@api_login.get("/get-user")
 | 
				
			||||||
@spec.validate(
 | 
					@spec.validate(
 | 
				
			||||||
    resp=Response(
 | 
					    resp=Response(
 | 
				
			||||||
        HTTP_200=GetUserResponse,
 | 
					        HTTP_200=PlayerSchema,
 | 
				
			||||||
        HTTP_401=None,
 | 
					        HTTP_401=None,
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
    operation_id="get_user"
 | 
					    operation_id="get_user"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@requires_authentication
 | 
					@requires_authentication
 | 
				
			||||||
def get_user(player: Player, auth_session: AuthSession):
 | 
					def get_user(player: Player, auth_session: AuthSession):
 | 
				
			||||||
    if auth_session.player.steam_id != player.steam_id:
 | 
					    return PlayerSchema.from_model(player).dict(by_alias=True)
 | 
				
			||||||
        return GetUserResponse(
 | 
					 | 
				
			||||||
            steam_id=str(player.steam_id),
 | 
					 | 
				
			||||||
            username=player.username,
 | 
					 | 
				
			||||||
            is_admin=player.is_admin,
 | 
					 | 
				
			||||||
            real_user=PlayerSchema.from_model(auth_session.player)
 | 
					 | 
				
			||||||
        ).dict(by_alias=True)
 | 
					 | 
				
			||||||
    return GetUserResponse.from_model(player).dict(by_alias=True)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
@api_login.post("/authenticate")
 | 
					@api_login.post("/authenticate")
 | 
				
			||||||
def steam_authenticate():
 | 
					def steam_authenticate():
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,7 +3,6 @@ from typing import Optional
 | 
				
			||||||
from flask import abort, make_response, request
 | 
					from flask import abort, make_response, request
 | 
				
			||||||
from sqlalchemy.sql.operators import json_path_getitem_op
 | 
					from sqlalchemy.sql.operators import json_path_getitem_op
 | 
				
			||||||
from app_db import db
 | 
					from app_db import db
 | 
				
			||||||
from models import auth_session
 | 
					 | 
				
			||||||
from models.auth_session import AuthSession
 | 
					from models.auth_session import AuthSession
 | 
				
			||||||
from models.player import Player
 | 
					from models.player import Player
 | 
				
			||||||
from models.player_team import PlayerTeam
 | 
					from models.player_team import PlayerTeam
 | 
				
			||||||
| 
						 | 
					@ -14,7 +13,6 @@ def requires_authentication(f):
 | 
				
			||||||
    @wraps(f)
 | 
					    @wraps(f)
 | 
				
			||||||
    def decorator(*args, **kwargs):
 | 
					    def decorator(*args, **kwargs):
 | 
				
			||||||
        auth = request.cookies.get("auth")
 | 
					        auth = request.cookies.get("auth")
 | 
				
			||||||
        doas = request.cookies.get("doas")
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if not auth:
 | 
					        if not auth:
 | 
				
			||||||
            abort(401)
 | 
					            abort(401)
 | 
				
			||||||
| 
						 | 
					@ -30,30 +28,6 @@ def requires_authentication(f):
 | 
				
			||||||
        player = auth_session.player
 | 
					        player = auth_session.player
 | 
				
			||||||
        kwargs["player"] = player
 | 
					        kwargs["player"] = player
 | 
				
			||||||
        kwargs["auth_session"] = auth_session
 | 
					        kwargs["auth_session"] = auth_session
 | 
				
			||||||
 | 
					 | 
				
			||||||
        if doas and player.is_admin:
 | 
					 | 
				
			||||||
            doas_int = int(doas)
 | 
					 | 
				
			||||||
            if doas_int and doas_int != player.steam_id:
 | 
					 | 
				
			||||||
                doas_player = db.session.query(
 | 
					 | 
				
			||||||
                    Player
 | 
					 | 
				
			||||||
                ).where(
 | 
					 | 
				
			||||||
                    Player.steam_id == doas_int
 | 
					 | 
				
			||||||
                ).one_or_none()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                if doas_player:
 | 
					 | 
				
			||||||
                    kwargs["player"] = doas_player
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return f(*args, **kwargs)
 | 
					 | 
				
			||||||
    return decorator
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def requires_admin(f):
 | 
					 | 
				
			||||||
    @wraps(f)
 | 
					 | 
				
			||||||
    def decorator(*args, **kwargs):
 | 
					 | 
				
			||||||
        auth_session: AuthSession | None = kwargs["auth_session"]
 | 
					 | 
				
			||||||
        if not auth_session or not auth_session.player:
 | 
					 | 
				
			||||||
            abort(401)
 | 
					 | 
				
			||||||
        if not auth_session.player.is_admin:
 | 
					 | 
				
			||||||
            abort(403)
 | 
					 | 
				
			||||||
        return f(*args, **kwargs)
 | 
					        return f(*args, **kwargs)
 | 
				
			||||||
    return decorator
 | 
					    return decorator
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,32 +0,0 @@
 | 
				
			||||||
"""Add is_admin field
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Revision ID: f8588cdf998e
 | 
					 | 
				
			||||||
Revises: 3b18d4bfc6ac
 | 
					 | 
				
			||||||
Create Date: 2025-05-13 17:15:53.887878
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
"""
 | 
					 | 
				
			||||||
from alembic import op
 | 
					 | 
				
			||||||
import sqlalchemy as sa
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# revision identifiers, used by Alembic.
 | 
					 | 
				
			||||||
revision = 'f8588cdf998e'
 | 
					 | 
				
			||||||
down_revision = '3b18d4bfc6ac'
 | 
					 | 
				
			||||||
branch_labels = None
 | 
					 | 
				
			||||||
depends_on = None
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def upgrade():
 | 
					 | 
				
			||||||
    # ### commands auto generated by Alembic - please adjust! ###
 | 
					 | 
				
			||||||
    with op.batch_alter_table('players', schema=None) as batch_op:
 | 
					 | 
				
			||||||
        batch_op.add_column(sa.Column('is_admin', sa.Boolean(), nullable=False, default=False))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # ### end Alembic commands ###
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def downgrade():
 | 
					 | 
				
			||||||
    # ### commands auto generated by Alembic - please adjust! ###
 | 
					 | 
				
			||||||
    with op.batch_alter_table('players', schema=None) as batch_op:
 | 
					 | 
				
			||||||
        batch_op.drop_column('is_admin')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # ### end Alembic commands ###
 | 
					 | 
				
			||||||
| 
						 | 
					@ -12,7 +12,6 @@ class Player(app_db.BaseModel):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    steam_id: Mapped[int] = mapped_column(BigInteger, primary_key=True)
 | 
					    steam_id: Mapped[int] = mapped_column(BigInteger, primary_key=True)
 | 
				
			||||||
    username: Mapped[str] = mapped_column(String(63))
 | 
					    username: Mapped[str] = mapped_column(String(63))
 | 
				
			||||||
    is_admin: Mapped[bool] = mapped_column(default=False)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    teams: Mapped[list["PlayerTeam"]] = relationship(back_populates="player")
 | 
					    teams: Mapped[list["PlayerTeam"]] = relationship(back_populates="player")
 | 
				
			||||||
    auth_sessions: Mapped[list["AuthSession"]] = relationship(back_populates="player")
 | 
					    auth_sessions: Mapped[list["AuthSession"]] = relationship(back_populates="player")
 | 
				
			||||||
| 
						 | 
					@ -24,15 +23,10 @@ class Player(app_db.BaseModel):
 | 
				
			||||||
class PlayerSchema(spec.BaseModel):
 | 
					class PlayerSchema(spec.BaseModel):
 | 
				
			||||||
    steam_id: str
 | 
					    steam_id: str
 | 
				
			||||||
    username: str
 | 
					    username: str
 | 
				
			||||||
    is_admin: bool = False
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @classmethod
 | 
					    @classmethod
 | 
				
			||||||
    def from_model(cls, player: Player):
 | 
					    def from_model(cls, player: Player):
 | 
				
			||||||
        return cls(
 | 
					        return cls(steam_id=str(player.steam_id), username=player.username)
 | 
				
			||||||
            steam_id=str(player.steam_id),
 | 
					 | 
				
			||||||
            username=player.username,
 | 
					 | 
				
			||||||
            is_admin=player.is_admin
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from models.auth_session import AuthSession
 | 
					from models.auth_session import AuthSession
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,6 @@
 | 
				
			||||||
from flask import Blueprint, abort, make_response
 | 
					from flask import Blueprint
 | 
				
			||||||
from spectree import Response
 | 
					from spectree import Response
 | 
				
			||||||
from middleware import requires_admin, requires_authentication
 | 
					from middleware import requires_authentication
 | 
				
			||||||
from models.player import Player, PlayerSchema
 | 
					from models.player import Player, PlayerSchema
 | 
				
			||||||
from spec import spec, BaseModel
 | 
					from spec import spec, BaseModel
 | 
				
			||||||
from app_db import db
 | 
					from app_db import db
 | 
				
			||||||
| 
						 | 
					@ -23,53 +23,3 @@ def set_username(json: SetUsernameJson, player: Player, **kwargs):
 | 
				
			||||||
    player.username = json.username
 | 
					    player.username = json.username
 | 
				
			||||||
    db.session.commit()
 | 
					    db.session.commit()
 | 
				
			||||||
    return PlayerSchema.from_model(player).dict(by_alias=True), 200
 | 
					    return PlayerSchema.from_model(player).dict(by_alias=True), 200
 | 
				
			||||||
 | 
					 | 
				
			||||||
@api_user.get("/all")
 | 
					 | 
				
			||||||
@spec.validate(
 | 
					 | 
				
			||||||
    resp=Response(
 | 
					 | 
				
			||||||
        HTTP_200=list[PlayerSchema],
 | 
					 | 
				
			||||||
    ),
 | 
					 | 
				
			||||||
    operation_id="get_all_users",
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
@requires_authentication
 | 
					 | 
				
			||||||
@requires_admin
 | 
					 | 
				
			||||||
def get_all_users(player: Player, **kwargs):
 | 
					 | 
				
			||||||
    players = db.session.query(Player).all()
 | 
					 | 
				
			||||||
    return list(map(lambda p: PlayerSchema.from_model(p).dict(by_alias=True), players)), 200
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@api_user.put("/doas/<steam_id>")
 | 
					 | 
				
			||||||
@spec.validate(
 | 
					 | 
				
			||||||
    resp=Response(
 | 
					 | 
				
			||||||
        HTTP_200=PlayerSchema,
 | 
					 | 
				
			||||||
    ),
 | 
					 | 
				
			||||||
    operation_id="set_doas"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
@requires_authentication
 | 
					 | 
				
			||||||
@requires_admin
 | 
					 | 
				
			||||||
def set_doas(steam_id: str, **_):
 | 
					 | 
				
			||||||
    player = db.session.query(Player).where(
 | 
					 | 
				
			||||||
        Player.steam_id == steam_id
 | 
					 | 
				
			||||||
    ).one_or_none()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if not player:
 | 
					 | 
				
			||||||
        abort(404)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    resp = make_response(
 | 
					 | 
				
			||||||
        PlayerSchema.from_model(player).dict(by_alias=True)
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    resp.set_cookie("doas", steam_id, httponly=True)
 | 
					 | 
				
			||||||
    return resp
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@api_user.delete("/doas")
 | 
					 | 
				
			||||||
@spec.validate(
 | 
					 | 
				
			||||||
    resp=Response(
 | 
					 | 
				
			||||||
        HTTP_204=None,
 | 
					 | 
				
			||||||
    ),
 | 
					 | 
				
			||||||
    operation_id="unset_doas"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
@requires_authentication
 | 
					 | 
				
			||||||
@requires_admin
 | 
					 | 
				
			||||||
def unset_doas(**_):
 | 
					 | 
				
			||||||
    resp = make_response({ }, 204)
 | 
					 | 
				
			||||||
    resp.delete_cookie("doas", httponly=True)
 | 
					 | 
				
			||||||
    return resp
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue