diff --git a/.env.example b/.env.example index dbb4405..71ade86 100644 --- a/.env.example +++ b/.env.example @@ -4,4 +4,4 @@ LOGIN_URL=https://login.datasektionen.se LOGIN_KEY=asdfasdfasdfsadfsadfasdf PLS_URL=https://pls.datasektionen.se -DB_URL=postgresql://:@localhost:5432/durn \ No newline at end of file +DATABASE_URL=postgresql://:@localhost:5432/durn diff --git a/Readme.md b/Readme.md index 86abbda..7985c6d 100644 --- a/Readme.md +++ b/Readme.md @@ -1,6 +1,6 @@ -# dUrn - the voting system +# smUrn - Digitala omröstningar -This is a implementation of a voting system for the Computer Science Chapter, with a backend written in golang and a frontend written in Typescript React. +This is a implementation of another voting system for the Computer Science Chapter, with a backend written in golang and a frontend written in Typescript React. @@ -25,7 +25,8 @@ The system uses the following permissions in pls: | `LOGIN_URL` | `https://login.datasektionen.se` | url for the login system and API | | `LOGIN_KEY` | | API-key for the login system | | `PLS_URL` | `https://pls.datasektionen.se` | url for the permissions system pls | -| `DATABASE_URL` | | postgres-url for connecting to the database instance | +| `PLS_SYSTEM_NAME` | `durn` | the system to check for permissions in pls | +| `DATABASE_URL` | | postgres-url for connecting to the database instance | ## How to run @@ -44,4 +45,4 @@ The system uses the following permissions in pls: 2. Setup environment variables 3. Run `make prod` in root -The system also has a `dockerfile` setup for deployment. \ No newline at end of file +The system also has a `dockerfile` setup for deployment. diff --git a/client/src/components/AdminElectionView.tsx b/client/src/components/AdminElectionView.tsx index 34ca4c5..92d64f6 100644 --- a/client/src/components/AdminElectionView.tsx +++ b/client/src/components/AdminElectionView.tsx @@ -80,29 +80,9 @@ export const AdminElectionView: React.FC = ({
-
- - Election starts - - -
- -
- - Election ends - - -
-
- Mandates + Antal alternativ att välja = ({ />
-
- - Secondary mandates - - -
-
- Submitted votes + Antal röster {submittedVotes ?? "-"} @@ -162,4 +132,4 @@ export const AdminElectionView: React.FC = ({ ; -} \ No newline at end of file +} diff --git a/client/src/components/Authentication.tsx b/client/src/components/Authentication.tsx index 7b481cc..d9bdfe7 100644 --- a/client/src/components/Authentication.tsx +++ b/client/src/components/Authentication.tsx @@ -7,7 +7,7 @@ import { } from "react-router-dom"; export const Login: React.FC = () => { - const loginURL = "https://login.datasektionen.se" + const loginURL = "https://sso.datasektionen.se/legacyapi" const callback = encodeURIComponent(`${window.location.origin}/#/token/`) const url = `${loginURL}/login?callback=${callback}`; @@ -83,4 +83,4 @@ export const Token: React.FC = () => { }, [token]) return <>; -} \ No newline at end of file +} diff --git a/client/src/components/CandidateList.tsx b/client/src/components/CandidateList.tsx index 7809bd0..c815732 100644 --- a/client/src/components/CandidateList.tsx +++ b/client/src/components/CandidateList.tsx @@ -64,14 +64,14 @@ export const CandidateList: React.FC = ( setName(element.target.value)} /> setPresentation(element.target.value)} /> @@ -83,7 +83,7 @@ export const CandidateList: React.FC = ( - Add new candidate + Lägg till alternativ @@ -108,12 +108,12 @@ export const CandidateList: React.FC = ( @@ -183,4 +183,4 @@ const CandidateRow: React.FC = ( -}; \ No newline at end of file +}; diff --git a/client/src/components/DisplayResult.tsx b/client/src/components/DisplayResult.tsx index 3cf091c..0fd5030 100644 --- a/client/src/components/DisplayResult.tsx +++ b/client/src/components/DisplayResult.tsx @@ -148,17 +148,17 @@ export const DisplaySchultzeResult: React.FC = ( { } return <> -

Election Result

+

Röstresultat

{firstSymbolic > 0 && <> - Ordinarie + SM föredrog följande alternativ
- Name of the candidate + Alternativ - Candidate presentation + Beskrivning
- + @@ -214,13 +214,13 @@ export const DisplaySchultzeResult: React.FC = ( { {(ranking.length > election.mandates + election.extraMandates || firstSymbolic < ranking.length) && <> - Non-Elected + SM föredrog INTE följade alternativ
Rank Candidate Alternativ
- + @@ -245,7 +245,7 @@ export const DisplaySchultzeResult: React.FC = ( {
Rank Candidate Alternativ

-

Voting data

+

Röstdata

= ( ; return <> - Candidate index: + +

Totala antalet röster: {votes}

+ + Alternativindex: {ranking.map((c, i) => ( {labels[i]}
}> @@ -313,10 +316,9 @@ const DisplayVoteData: React.FC = ( ))} -

Total amount of votes: {votes}

- Vote matrix + Röstmatris


@@ -326,7 +328,7 @@ const DisplayVoteData: React.FC = (

- Schultze result matrix + Schulzeresultatmatris


@@ -342,4 +344,4 @@ const DisplayVoteData: React.FC = ( -} \ No newline at end of file +} diff --git a/client/src/components/ElectionInfo.tsx b/client/src/components/ElectionInfo.tsx index b0b9fcc..757c920 100644 --- a/client/src/components/ElectionInfo.tsx +++ b/client/src/components/ElectionInfo.tsx @@ -87,6 +87,7 @@ export const DisplayElectionInfo: React.FC = (

{election.name}

+ {/*

{election.description}

@@ -100,6 +101,7 @@ export const DisplayElectionInfo: React.FC = (

{election.extraMandates} Secondary mandates

} + */}
-} \ No newline at end of file +} diff --git a/client/src/components/Voting.tsx b/client/src/components/Voting.tsx index 78db796..65124d9 100644 --- a/client/src/components/Voting.tsx +++ b/client/src/components/Voting.tsx @@ -101,7 +101,9 @@ const useStyles = createStyles((theme) => ({ info : { padding: "1rem", + paddingBottom: "0.5rem", marginBottom: "1rem", + marginTop: "2rem", borderRadius: "0.5rem", backgroundColor: "rgb(197, 202, 233)", }, @@ -138,9 +140,9 @@ const InfoBox: React.FC = () => { return

- Rank the the candidates in your preferred order.

- Note that the ordering of the candidates that are ranked below Vakant is taken into account.

- You will be able to change your vote once it is submitted + Sätt det alternativ du vill rösta på överst.
+ Notera att ordningen på alla alternativ tas i beaktning.
+ Det går att ändra sin röst.

} @@ -193,11 +195,11 @@ export const Voting: React.FC = ({ }] = useDisclosure(false); const hasOpened = useMemo(() => ( - (election.openTime ? dayjs(Date.now()).isAfter(election.openTime) : false) + (election.openTime ? dayjs(Date.now()).isAfter(election.openTime) : true) ), [election.openTime]); const hasClosed = useMemo(() => ( - (election.closeTime ? dayjs(Date.now()).isAfter(election.closeTime) : true) + (election.closeTime ? dayjs(Date.now()).isAfter(election.closeTime) : false) ), [election.closeTime]); const disabled = useMemo(() => ( @@ -286,7 +288,7 @@ export const Voting: React.FC = ({ )) return <> -
+

{election.description}

@@ -320,20 +322,20 @@ export const Voting: React.FC = ({
{(election.finalized || (hasClosed && hasOpened)) && -

It is no longer possible to vote in this election.

+

Du kan inte längre rösta i denna omröstning.

} {!mayVote && !hasVoted &&

- You don't have the right to vote in this election
- Contact the Election Committee if you are a member that should have this right.
- (valberedningen@datasektionen.se) + Du saknar rättigheten att rösta i denna omröstning
+ Kontakta styreslen om du tror att något är fel.
+ (drek@datasektionen.se)

} {!election.finalized && !hasOpened && mayVote && -

This election hasn't been opened yet.

+

Omröstningen är inte öppen ännu.

} {/* {!(election.finalized || hasClosed || !hasOpened) && hasVoted && @@ -345,8 +347,7 @@ export const Voting: React.FC = ({ {!disabled && !loadingHasVoted && hasVoted &&

- You have voted in this election already, but it is possible to change your vote if needed!
- Note that the order of the candidates are randomized each time you load the page, and not necessarily the same as the order you previously voted in. + Du har röstat i den här omröstning redan, men det går att ändra sin röst om det behövs.

} @@ -364,16 +365,19 @@ export const Voting: React.FC = ({ {/* - Are you sure you want to submit your vote? It can't be changed once submitted. + Är du säker på att du vill rösta? Du kan inte ändra din röst när du väl röstat. */} - window.location.assign("/")} centered title="Vote successfully submitted"> + window.location.assign("/")} centered + title="Röst mottagen" + > - Your vote has successfully been submitted! You voted in the following order: + Du röstade med följande rankning
{submittedVoteOrder.map((candidate, i) => ( @@ -383,7 +387,7 @@ export const Voting: React.FC = ({ ))}
@@ -393,7 +397,7 @@ export const Voting: React.FC = ({
@@ -460,12 +464,12 @@ const DraggableCandidate: React.FC = ({
{candidate.presentation != "" && !candidate.symbolic ? -
- Presentation +
+ {candidate.presentation}
: <>}
}} -} \ No newline at end of file +} diff --git a/client/src/index.html b/client/src/index.html index aabb665..846f761 100644 --- a/client/src/index.html +++ b/client/src/index.html @@ -3,9 +3,9 @@ - + - dUrn - the voting system + smUrn - Digitala omröstningar diff --git a/client/src/views/Home.tsx b/client/src/views/Home.tsx index 9131f76..bff4c41 100644 --- a/client/src/views/Home.tsx +++ b/client/src/views/Home.tsx @@ -31,30 +31,27 @@ const Info: React.FC = () => { const { classes, cx } = useStyles() return
-

What is an urnval?

+

Vad är smUrn?

- An urnval is a kind of election where you can vote ahead of time, and where voting is done through a ranking of all candidates.
- In Datasektionen, we use urnval for the posts: "Ordförande", "Vice Ordförande", "Kassör" and "Kårfullmäktige".
- More information about the posts can be found at dfunkt.datasektionen.se. + smUrn är ett digitalt omröstningssystem som är baserat på sektionens system för digitala urnval, dUrn. + Systemet är primärt ämnat för användning under SM, därav namnet.

- -

How do I vote?

+ +

Hur röstar jag?

- Click on one of the open elections, rank the candidates in your preferred order, and press "Vote". + Klicka på en tillgänglig omröstning, rangordna dina val och klicka på "Rösta"

-

Questions or technical problems?

+

Frågor eller tekniska problem?

- Contact the Election Committee (valberedningen@datasektionen.se) - or the System Administrator (d-sys@datasektionen.se) + Kontakta Styrelsen (drek@datasektionen.se) + eller Systemansvarig (d-sys@datasektionen.se)

-

Source Code and other Information

+

Källkod och övrig information

- In order for the vote counting system to be as transparent as possible, the full source code - is available at github. The system and vote counting is - also described at the info page + Källkoden finns tillgänglig på en branch på github. Mer information går att finna på infosidan

} @@ -68,14 +65,14 @@ export const Home: React.FC = () => { ); return (<> -
+
{!loggedIn &&

- Log in to see all open elections. + Logga in för att se alla tillgängliga omröstningar.

} @@ -88,7 +85,7 @@ export const Home: React.FC = () => { {elections.filter((e) => !e.finalized).length == 0 &&

- There are currently no open urnval. + Det finns inga tillgängliga omröstningar.

} @@ -105,4 +102,4 @@ export const Home: React.FC = () => {
) -} \ No newline at end of file +} diff --git a/client/src/views/Info.tsx b/client/src/views/Info.tsx index c4831a4..172832f 100644 --- a/client/src/views/Info.tsx +++ b/client/src/views/Info.tsx @@ -18,52 +18,43 @@ const Info: React.FC = () => {
-

What is this system?

+

Vad är smUrn?

- Durn is a system for allowing voting in an election over a extended period of time using ranked ballots. - We use this system for the posts "Ordförande", "Vice Ordförande", "Kassör" and "Kårfullmäktige". - This is the third iteration of this system, the first having been hacked together in a short time - and then stopped working after running for a few years, and the second never being finished. + smUrn är ett digitalt omröstningssystem som är baserat på sektionens system för digitala urnval, dUrn. + Systemet är primärt ämnat för användning under SM, därav namnet. +

+ Detta är tredje (egentligen andra) iterationen av Konglig Datasektionens digitala omrösningssystem. + Det första systemet kallades för Mentometer och hackades ihop som hastigast på en pub. + Mentometer fungerade bra i flera år tills en omröstning i ett val där systemet gick sönder och alla röster hamnade på vakans. + "Osäkert", tänkte alla inblandade och dödade Mentometer. +

+ Efter Mentometer gick sektionen över till VoteIT, ett system för stämmor som THS erbjöd alla sektioner. + VoteIT fördröjde varje SM med ~1 timme på grund av hur dåligt det fungerade och att de ändrade sin UI mellan varje SM. + Det enda bra med VoteIT var att man kunde vinka genom att trycka på en knapp. +

+ Hösten 2023 byggdes smUrn till Budget-SM för att slippa VoteIT. + smUrn var kraftigt baserat på sektionens digitala urnnvalssystem dUrn som byggdes våren 2023.

-

How are the votes counted?

+

Hur räknas rösterna?

- Exactly how our urnval is supposed to work is described in - our reglemente in §3.12.7 Urnval. -

- The system uses a vote counting algorithm called the "Shultze Method", which operates on ranked ballots. It has quite - a few desirable properties, one of the major ones for our interests being that it produces a ranking of the candidates. - Exactly how it works and all of the properties it has is described in - its Wikipedia article, - which is very throughout and descriptive and describes it much better than what could fit here. + Det alternativ som får flest röster är det som vinner. (duh) + För att gå in lite på djupet så används något som kallas för "Shulze-Metoden". + Exakt hur det fungerar kan man läsa om på Wikipediasidan. + "Shulze-Metoden" är egentligen ganska overkill då metoden inte spelar någon roll när det bara finns 2 val men används för att dUrn gör det.

-

Why can't my vote be changed after voting?

+

Varför kan jag inte ändra min röst efter att jag har röstat?

- This is not true anymore, it is now possible to change your vote. + Numera så går det faktiskt att ändra sin röst. + Vill man läsa mer om varför dUrn fungerar på det sättet så kan man gå in på dUrns infosida.

- {/*

- This is due to a balancing of the interests of security and having a good user experience. The simple solution - for allowing this would be to store which user made each vote in the database. This would however allow anyone with - database access (through a leak or admin access) to see what any and all persons voted for. A possible idea for - a solution for this would be to introduce some kind of hash of the users information, and instead store that. - However, we don't have access to any kind of information to create this hash that isn't either public or not permanent, or easily bruteforced. - This could be solved by having the user provide some kind of information on their own that could be used. This would - effectively be the same as the user creating a password used for voting. However, this is somewhat overkill, and - having such a password was one of the bigger usability complaints for the previous system. It also brings with it all - the security problems with people choosing weak passwords, or possibly even reusing them from other places. - The last point in particular brings a lot of responsibility in regards to the security of the system. -

- This is not a perfect solution, and is a balancing of interests, how this is implemented could be changed in the future. -

*/} - -

Source Code

- In order to be as transparent as possible, the source code for the system is available - at github. +

Källkod

+ Källkoden finns tillgänglig på en branch på github.
} -export default Info; \ No newline at end of file +export default Info; diff --git a/client/src/views/admin/EditElection.tsx b/client/src/views/admin/EditElection.tsx index f73ca36..90a09fb 100644 --- a/client/src/views/admin/EditElection.tsx +++ b/client/src/views/admin/EditElection.tsx @@ -78,7 +78,7 @@ const EditElection: React.FC = () => { closeTime: electionData.closeTime, }); candidatesHandler.setState( - electionData.candidates.filter((c: Candidate) => !c.symbolic) + electionData.candidates .map((c: Candidate) => ({ ...c, changed: false, @@ -352,4 +352,4 @@ const EditElection: React.FC = () => { } -export default EditElection; \ No newline at end of file +export default EditElection; diff --git a/config/config.go b/config/config.go index 2e995a2..c5a89f8 100644 --- a/config/config.go +++ b/config/config.go @@ -10,19 +10,14 @@ import ( ) type Config struct { - HOST string - PORT int - LOGIN_URL string - LOGIN_KEY string - PLS_URL string + HOST string + PORT int + LOGIN_URL string + LOGIN_KEY string + PLS_URL string + PLS_SYSTEM_NAME string DATABASE_URL string - - DB_HOST string - DB_PORT int - DB_NAME string - DB_USER string - DB_PSWD string } var ( @@ -59,19 +54,14 @@ func GetConfig() *Config { } conf = Config{ - HOST: loadStringEnv("HOST", "https://localhost.datasektionen.se"), - PORT: loadIntEnv("PORT", 3000), - LOGIN_URL: loadStringEnv("LOGIN_URL", "https://login.datasektionen.se"), - LOGIN_KEY: loadStringEnv("LOGIN_KEY", ""), - PLS_URL: loadStringEnv("PLS_URL", "https://pls.datasektionen.se"), + HOST: loadStringEnv("HOST", "https://localhost.datasektionen.se"), + PORT: loadIntEnv("PORT", 3000), + LOGIN_URL: loadStringEnv("LOGIN_URL", "https://login.datasektionen.se"), + LOGIN_KEY: loadStringEnv("LOGIN_KEY", ""), + PLS_URL: loadStringEnv("PLS_URL", "https://pls.datasektionen.se"), + PLS_SYSTEM_NAME: loadStringEnv("PLS_SYSTEM_NAME", "durn"), DATABASE_URL: loadStringEnv("DATABASE_URL", ""), - - DB_HOST: loadStringEnv("DB_HOST", ""), - DB_PORT: loadIntEnv("DB_PORT", 5432), - DB_NAME: loadStringEnv("DB_NAME", "durn"), - DB_USER: loadStringEnv("DB_USER", "durn"), - DB_PSWD: loadStringEnv("DB_PSWD", ""), } loaded = true diff --git a/public/favicon-sm.png b/public/favicon-sm.png new file mode 100644 index 0000000..95a00ac Binary files /dev/null and b/public/favicon-sm.png differ diff --git a/server/actions/elections.go b/server/actions/elections.go index c175516..a1975ba 100644 --- a/server/actions/elections.go +++ b/server/actions/elections.go @@ -70,7 +70,6 @@ func CreateElection(c *gin.Context) { } db := database.GetDB() - defer database.ReleaseDB() election := database.Election{ ID: uuid.NewV4(), Name: body.Name, @@ -82,21 +81,21 @@ func CreateElection(c *gin.Context) { Published: false, Finalized: false, } - vacant := database.Candidate{ - ID: uuid.NewV4(), - Name: util.VacantCandidate, - Presentation: "", - ElectionID: election.ID, - Symbolic: true, - } + // vacant := database.Candidate{ + // ID: uuid.NewV4(), + // Name: util.VacantCandidate, + // Presentation: "", + // ElectionID: election.ID, + // Symbolic: true, + // } if err := db.Transaction(func(tx *gorm.DB) error { - if err := db.Create(&election).Error; err != nil { - return err - } - if err := db.Create(&vacant).Error; err != nil { + if err := tx.Create(&election).Error; err != nil { return err } + // if err := tx.Create(&vacant).Error; err != nil { + // return err + // } return nil }); err != nil { fmt.Println(err) @@ -135,7 +134,6 @@ func EditElection(c *gin.Context) { election := database.Election{ID: electionId} db := database.GetDB() - defer database.ReleaseDB() if err := db.Preload("Candidates").First(&election).Error; err != nil { fmt.Println(err) c.String(http.StatusBadRequest, util.InvalidElectionMessage) @@ -154,6 +152,9 @@ func EditElection(c *gin.Context) { if body.Description != nil { election.Description = *body.Description } + if body.Mandates != nil { + election.Mandates = *body.Mandates + } if body.OpenTime != nil { election.OpenTime = util.ConvertNullTime(*body.OpenTime) } @@ -179,7 +180,6 @@ func setElectionPublishedStatus(c *gin.Context, publishedStatus bool) { election := database.Election{ID: electionId} db := database.GetDB() - defer database.ReleaseDB() if err := db.Preload("Candidates").First(&election).Error; err != nil { fmt.Println(err) c.String(http.StatusBadRequest, util.InvalidElectionMessage) @@ -219,7 +219,6 @@ func FinalizeElection(c *gin.Context) { election := database.Election{ID: electionId} db := database.GetDB() - defer database.ReleaseDB() if err := db.Preload("Candidates").First(&election).Error; err != nil { fmt.Println(err) c.String(http.StatusBadRequest, util.InvalidElectionMessage) @@ -248,7 +247,6 @@ func DeleteElection(c *gin.Context) { election := database.Election{ID: electionId} db := database.GetDB() - defer database.ReleaseDB() if err := db.Preload("Votes").First(&election).Error; err != nil { fmt.Println(err) c.String(http.StatusBadRequest, util.InvalidElectionMessage) @@ -286,7 +284,6 @@ func GetElection(c *gin.Context) { } db := database.GetDB() - defer database.ReleaseDB() election := database.Election{ID: electionId} if err := db.Preload("Candidates").First(&election).Error; err != nil { @@ -302,7 +299,6 @@ func GetElection(c *gin.Context) { // candidates in the elections. func GetElections(c *gin.Context) { db := database.GetDB() - defer database.ReleaseDB() var elections []database.Election if err := db.Preload("Candidates").Find(&elections).Error; err != nil { @@ -322,7 +318,6 @@ func GetElections(c *gin.Context) { // published flag set to true. func GetPublicElections(c *gin.Context) { db := database.GetDB() - defer database.ReleaseDB() var elections []database.Election if err := db.Preload("Candidates").Find(&elections).Error; err != nil { @@ -354,7 +349,6 @@ func GetPublicElection(c *gin.Context) { } db := database.GetDB() - defer database.ReleaseDB() // election := database.FetchElectionIfPublic(db, electionId) election := database.Election{ID: electionId} @@ -389,13 +383,8 @@ func AddCandidate(c *gin.Context) { c.String(http.StatusBadRequest, util.BadParametersMessage) return } - if body.Name == util.BlankCandidate || body.Name == util.VacantCandidate { - c.String(http.StatusBadRequest, fmt.Sprintf("'%s' is a reserved candidate name", body.Name)) - return - } db := database.GetDB() - defer database.ReleaseDB() election := database.Election{ID: electionId} if err := db.Preload("Votes").First(&election).Error; err != nil { @@ -424,7 +413,7 @@ func AddCandidate(c *gin.Context) { Name: body.Name, Presentation: body.Presentation, ElectionID: electionId, - Symbolic: false, + Symbolic: body.Name == util.BlankCandidate || body.Name == util.VacantCandidate, } if err := db.Create(&candidate).Error; err != nil { fmt.Println(err) @@ -456,7 +445,6 @@ func EditCandidate(c *gin.Context) { candidate := database.Candidate{ID: candidateId} db := database.GetDB() - defer database.ReleaseDB() if err := db.First(&candidate).Error; err != nil { fmt.Println(err) c.String(http.StatusBadRequest, "Invalid candidate specified") @@ -490,7 +478,6 @@ func RemoveCandidate(c *gin.Context) { candidate := database.Candidate{ID: candidateId} db := database.GetDB() - defer database.ReleaseDB() if err := db.Preload("Election.Votes").First(&candidate).Error; err != nil { c.String(http.StatusBadRequest, "Invalid candidate specified") return diff --git a/server/actions/voters.go b/server/actions/voters.go index 8c1c86a..d04cab9 100644 --- a/server/actions/voters.go +++ b/server/actions/voters.go @@ -34,7 +34,6 @@ func AddVoters(c *gin.Context) { } db := database.GetDB() - defer database.ReleaseDB() if err := db.Clauses(clause.OnConflict{DoNothing: true}).Create(&voters).Error; err != nil { fmt.Println(err) @@ -70,7 +69,6 @@ func RemoveVoters(c *gin.Context) { } db := database.GetDB() - defer database.ReleaseDB() if err := db.Delete(&voters).Error; err != nil { fmt.Println(err) @@ -90,7 +88,6 @@ func RemoveVoters(c *gin.Context) { // GetVoters fetches all current allowed voters from the database func GetVoters(c *gin.Context) { db := database.GetDB() - defer database.ReleaseDB() result, err := getAllVoters(db) if err != nil { diff --git a/server/actions/votes.go b/server/actions/votes.go index a9c1c3e..8185a29 100644 --- a/server/actions/votes.go +++ b/server/actions/votes.go @@ -53,7 +53,6 @@ func CastVote(c *gin.Context) { } db := database.GetDB() - defer database.ReleaseDB() election := database.Election{ID: electionId} @@ -164,7 +163,6 @@ func GetVotes(c *gin.Context) { } db := database.GetDB() - defer database.ReleaseDB() var votes []database.Vote if err := db.Preload("Rankings").Find(&votes, "election_id = ?", electionId).Error; err != nil { @@ -206,7 +204,6 @@ func GetVoteCount(c *gin.Context) { } db := database.GetDB() - defer database.ReleaseDB() var count int64 if err := db.Model(database.Vote{}).Where("election_id = ?", electionId).Count(&count).Error; err != nil { @@ -239,7 +236,6 @@ func CountVotes(c *gin.Context) { c.String(http.StatusBadRequest, util.InvalidElectionMessage) return } - database.ReleaseDB() if !election.Finalized { c.String(http.StatusBadRequest, "Can't count votes of unfinalized election") return @@ -350,7 +346,6 @@ func CountVotesSchultze(c *gin.Context) { c.String(http.StatusBadRequest, util.InvalidElectionMessage) return } - database.ReleaseDB() if !election.Finalized { c.String(http.StatusBadRequest, "Can't count votes of unfinalized election") return @@ -450,7 +445,6 @@ func GetHashes(c *gin.Context) { // TODO: possibly add electionID to database for hashes, since it would be nice // to be able to filter by that and only allow fetching from finalized elections db := database.GetDB() - defer database.ReleaseDB() var hashes []database.VoteHash if err := db.Find(&hashes).Error; err != nil { @@ -478,7 +472,6 @@ func HasVoted(c *gin.Context) { user := c.GetString("user") db := database.GetDB() - defer database.ReleaseDB() if db.Find(&database.CastedVote{ElectionID: electionId, Email: user}).RowsAffected == 0 { c.String(http.StatusOK, "false") diff --git a/server/db/db.go b/server/db/db.go index 59fb6bc..bfa211e 100644 --- a/server/db/db.go +++ b/server/db/db.go @@ -4,8 +4,6 @@ import ( "fmt" "os" - // "sync" - "gorm.io/driver/postgres" "gorm.io/gorm" @@ -14,8 +12,6 @@ import ( var db *gorm.DB -// var m sync.Mutex - func InitDB() { c := config.GetConfig() dsn := c.DATABASE_URL @@ -35,14 +31,9 @@ func InitDB() { } func GetDB() *gorm.DB { - // m.Lock() return db } -func ReleaseDB() { - // m.Unlock() -} - // ReorderRows shuffles the rows in the specified table // O(N log N) ? func ReorderRows(db *gorm.DB, table string) error { diff --git a/server/middleware/auth.go b/server/middleware/auth.go index 4c91575..b2ab59c 100644 --- a/server/middleware/auth.go +++ b/server/middleware/auth.go @@ -58,6 +58,7 @@ func Authenticate() gin.HandlerFunc { func Authorize() gin.HandlerFunc { conf := config.GetConfig() url := conf.PLS_URL + systemName := conf.PLS_SYSTEM_NAME if check, err := http.Get(url + "/"); err != nil || check.StatusCode != 200 { fmt.Println(err) @@ -66,7 +67,7 @@ func Authorize() gin.HandlerFunc { return func(c *gin.Context) { user := c.GetString("userid") - requestURL := fmt.Sprintf("%s/api/user/%s/durn", url, user) + requestURL := fmt.Sprintf("%s/api/user/%s/%s", url, user, systemName) var response []string diff --git a/server/middleware/voting.go b/server/middleware/voting.go index 7701f55..c24d959 100644 --- a/server/middleware/voting.go +++ b/server/middleware/voting.go @@ -19,10 +19,8 @@ func AllowedToVote() gin.HandlerFunc { if db.Find(&database.ValidVoter{Email: user}).RowsAffected == 0 { c.String(http.StatusForbidden, "Not registered as a valid voter") c.Abort() - database.ReleaseDB() return } - database.ReleaseDB() c.Next() } } diff --git a/server/util/misc.go b/server/util/misc.go index e5c8ad1..09a1d79 100644 --- a/server/util/misc.go +++ b/server/util/misc.go @@ -16,7 +16,7 @@ func ValidEmail(email string) bool { // both a start and an end. func TimeIsInValidInterval(time time.Time, start sql.NullTime, end sql.NullTime) bool { if !start.Valid || !end.Valid { - return false + return true } if time.Before(start.Time) || time.After(end.Time) { return false